目录
- 前言
-
- Hql的介绍
- Hql语句的特性
-
- HQL语句支持占位符
- HQL支持连接查询
- HQL支持聚合函数
- HQL分页
- Hql特性的运用(模糊查询,分页)
-
- 运用基本特性逻辑
- 运用辅助Dao方法减少开发周期(BaseDao)
- 总结
前言
本章节我们将会通过结合之前的案例来详细讲解一下Hql语句的运用。
比如
在里面的 “from Order” 这就算是Hql语句的一种
那么查询所有,用这种方法就可以实现,那么问题就这么来了,
如果我想传个参数,然后根据参数查询,或者用来分页,那么这个时候Hql语句又如何去写?
欧克,Let`go
Hql的介绍
Hql: 简称Hibernate的面向对象语言
Hibernate Query Language的缩写
那么让我们来看一看Hql和sql语句的区别。
HQL | SQL |
---|---|
类名/属性 | 表名/列名 |
区分大小写,关键字不区分大小写 | 不区分大小写 |
别名 | 别名 |
?,从下标0开始计算位置(hibernate5之后不支持) | ?,从顺序1开始计算位置 |
:命名参数 | 不支持:命名参数 |
面向对象的查询语言 | 面向结构查询语言 |
嘛,接下来就是一整套的测试数据
Hql语句的特性
返回对象(多个)
public void testList1() {
Query query = session.createQuery("from Book");
List<Book> list = query.list();
for (Book b : list) {
System.out.println(b);
}
}
返回单个列段,用字符串就可以接受
public void testList2() {
Query query = session.createQuery("select b.bookName as ss from Book b");
List<String> list = query.list();
for (String b : list) {
System.out.println(b);
}
}
查两个列段及以上,默认返回的是Object【】
public void testList3() {
Query query = session.createQuery("select b.bookId,b.bookName as ss from Book b");
List<Object[]> list = query.list();
for (Object[] b : list) {
System.out.println(Arrays.toString(b));
}
}
注意map是函数,所以不区分大小写,返回的是map集合
public void testList4() {
Query query = session.createQuery("select new mAp(b.bookId,b.bookName) from Book b");
List<Map> list = query.list();
for (Map b : list) {
System.out.println(b);
}
}
查两个列段及以上,也可返回对象,前提是有对应的构造函数
public void testList5() {
Query query = session.createQuery("select new Book(b.bookId,b.bookName) from Book b");
List<Book> list = query.list();
for (Book b : list) {
System.out.println(b);
}
}
HQL语句支持占位符
public void testList6() {
Query query = session.createQuery("from Book where bookId in (:bookIds)");
query.setParameterList("bookIds", new Integer[] {1,2,4});
List<Book> list = query.list();
for (Book b : list) {
System.out.println(b);
}
}
HQL支持连接查询
public void testList7() {
Query query = session.createQuery("select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order");
List<Object[]> list = query.list();
for (Object[] b : list) {
System.out.println(Arrays.toString(b));
}
}
HQL支持聚合函数
public void testList8() {
Query query = session.createQuery("select count(*) from Book");
Long singleResult = (Long) query.getSingleResult();
System.out.println(singleResult);
}
HQL分页
public void testList9() {
Query query = session.createQuery("from Book");
query.setFirstResult(2);
query.setMaxResults(3);
List<Book> list = query.list();
for (Book b : list) {
System.out.println(b);
}
}
Hql特性的运用(模糊查询,分页)
运用基本特性逻辑
通过上面的特性讲解,大概也了解了基本特性
所以我们就可以来写个方法来测试是否可以使用模糊查询。
为了大家理解,就不直接放代码,而是一步一步来。
一,根据参数的有无而拼接hql语句
一般而言我们是直接从request请求中获取map集合里面的参数
可这边因为是测试,所以没有前端这一说。
切记不要搞混了!!!
//获取参数
String bookName = book.getBookName();
String Hql = "from Book where 1=1 ";
//根据参数的有无而拼接hql语句,所用的是命名参数
if(StringUtils.isNotBlank(bookName)) {
Hql+=" and bookName like :bookname ";
}
里面的 :bookname 是命名参数的写法 ,也就是已键值对的方式存在.
二,下面需要对query所赋值
ok,在我的看法中,我就直接分为两个部分,在这个部分中就是对query所赋值
横竖都是赋值,只不过需要在赋值之前加个判断
//下面需要对query所赋值
Query query = session.createQuery(Hql);
if(StringUtils.isNotBlank(bookName)) {
query.setParameter("bookname", "%"+bookName+"%");
}
//判断是否需要分页
if(pageBean!=null && pageBean.isPagination()) {
query.setFirstResult(pageBean.getStartIndex());
query.setMaxResults(pageBean.getRows());
}
三,整体代码展示
其实如果把之前的查询所有,和我刚才讲的来想一想的话其实还是差不多的。
偌:
public List<Book> list1(Book book,PageBean pageBean) {
Session session = SessionFactoryUtils.openSession();
Transaction transaction = session.beginTransaction();
String Hql = "from Book where 1=1 ";
//下面需要对query所赋值
Query query = session.createQuery(Hql);
List<Book> list = query.list();
transaction.commit();
session.close();
return list;
}
啊啊,整体代码就是这样:
public List<Book> list1(Book book,PageBean pageBean) {
Session session = SessionFactoryUtils.openSession();
Transaction transaction = session.beginTransaction();
//获取参数
String bookName = book.getBookName();
String Hql = "from Book where 1=1 ";
//根据参数的有无而拼接hql语句
if(StringUtils.isNotBlank(bookName)) {
Hql+=" and bookName like :bookname ";
}
//下面需要对query所赋值
Query query = session.createQuery(Hql);
if(StringUtils.isNotBlank(bookName)) {
query.setParameter("bookname", "%"+bookName+"%");
}
//判断是否需要分页
if(pageBean!=null && pageBean.isPagination()) {
query.setFirstResult(pageBean.getStartIndex());
query.setMaxResults(pageBean.getRows());
}
List<Book> list = query.list();
transaction.commit();
session.close();
return list;
}
希望大家能看的懂,也能理解我的思路拉(✪ω✪)
运用辅助Dao方法减少开发周期(BaseDao)
在上面我们已经知道如何裸写代码了,那么这个还怕个啥子嘛。
那么为了理解,我就先给大家看写好后,所引用的Dao
是不是看到后,感觉是不是跟我的上面分解第一步差不多,只不过整体上没有了第二部分的代码
ps:用到了map那是因为是用来模拟从jsp所传值,请不要乱想!!
public List<Book> list2(Book book,PageBean pageBean) {
Session session = SessionFactoryUtils.openSession();
Transaction transaction = session.beginTransaction();
//获取参数
String bookName = book.getBookName();
String Hql = "from Book where 1=1 ";
Map<String, Object> map = new HashMap<>();
//根据参数的有无而拼接hql语句
if(StringUtils.isNotBlank(bookName)) {
Hql+=" and bookName like :bookname ";
map.put("bookname", bookName);
}
List<Book> list = executeQuery(session, map, Hql, pageBean);
transaction.commit();
session.close();
return list;
}
1,BaseDao中的一键赋值(辅助方法)
这个家伙的话大家也别到处乱想了,汗,
方法本身主要是在本类里面使用,作用:快速给query赋值
map是外面所传过来的,咱先不管是否是jsp传过来,还是自己创建的map集合。
这个就是将Map集合里面的数据全部给query赋值
public void setParam(Map<String, Object> map , Query query) {
if(map!=null&&map.size()>0) {
Set<Entry<String, Object>> entrySet = map.entrySet();
Object value = null;
for (Entry<String, Object> entry : entrySet) {
value = entry.getValue();
//获取来自参数的map的键值对
//判断每一个的值的类型然后分别对待
if(value instanceof Object[]) {
query.setParameterList(entry.getKey(), (Object[])value);
}
else if(value instanceof Collection) {
query.setParameterList(entry.getKey(), (Collection)value);
}
else {
query.setParameter(entry.getKey(), value);
}
}
}
}
2,BaseDao中的查询总行数(辅助方法)
这个比较简单,就是根据Hql去查询表内总行数
public String getCountHql(String Hql) {
int indexOf = Hql.toUpperCase().indexOf("FROM");
return "select count(*) "+Hql.substring(indexOf);
}
3,所使用方法和判断是否分页(引用方法)
这个,其实并不难,重点在需要分页的里面
它使用了两次 seesion.createQuery ,不明白的话就会搞混了,
其实就是给pageBean的total属性所赋值。
额,怎么说呢,就是因为你模糊查询后,所查到的数据绝对不是整张表的的条数嘛,
所以需要重新设置一下,
public List executeQuery(Session session,Map<String, Object> map,String Hql,PageBean pageBean ) {
List list = null;
if(pageBean!=null && pageBean.isPagination()) {
//------找到这个表内有多少数据
String countHql = this.getCountHql(Hql);
Query countQuery = session.createQuery(countHql);
this.setParam(map, countQuery);
pageBean.setTotal(countQuery.getSingleResult().toString());
//----------------------------------
//给需要分页的query设置值
Query query = session.createQuery(Hql);
query.setFirstResult(pageBean.getStartIndex());
query.setMaxResults(pageBean.getRows());
this.setParam(map, query);
list = query.list();
}
else {//不用分页的话
Query query = session.createQuery(Hql);
//给query的参数赋值
this.setParam(map, query);
list = query.list();
}
return list;
}
总结
哇,超额完成啊,有木有,
这次是我想一下,看能不能改一下风格滴,
本人觉得每个地方的讲解还算详细的啦|ू・ω・` )
Thanks♪(・ω・)ノ希望对大家有所帮助