【Hibernate之Hql语句五】

it2022-05-05  119

目录

前言Hql的介绍Hql语句的特性HQL语句支持占位符HQL支持连接查询HQL支持聚合函数HQL分页 Hql特性的运用(模糊查询,分页)运用基本特性逻辑运用辅助Dao方法减少开发周期(BaseDao) 总结

前言

本章节我们将会通过结合之前的案例来详细讲解一下Hql语句的运用。

比如

在里面的 “from Order” 这就算是Hql语句的一种

那么查询所有,用这种方法就可以实现,那么问题就这么来了,

如果我想传个参数,然后根据参数查询,或者用来分页,那么这个时候Hql语句又如何去写?

欧克,Let`go


Hql的介绍

Hql: 简称Hibernate的面向对象语言

Hibernate Query Language的缩写

那么让我们来看一看Hql和sql语句的区别。

HQLSQL类名/属性表名/列名区分大小写,关键字不区分大小写不区分大小写别名别名?,从下标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♪(・ω・)ノ希望对大家有所帮助


最新回复(0)