HQL是Hibernate Query Language的缩写,提供更加丰富灵活、更为强大的查询能力;HQL更接近SQL语句查询语法。
1、sql 面向数据库表查询。
2、hql 面向对象查询。
3、hql : from 后面跟的 类名+类对象 where 后 用 对象的属性做条件。
4、sql: from 后面跟的是表名 where 后 用表中字段做条件查询。
5、在Hibernate中使用查询时,一般使用Hql查询语句。
6、HQL,即Hibernate的查询语言跟SQL非常相像。不过HQL与SQL的最根本的区别,就是它是面向对象的。
7.大小写敏感:因为HQL是面向对象的,而对象类的名称和属性都是大小写敏感的,所以HQL是大小写敏感的。
8sql的占位符是?,而hql的是命名参数
下面多种结果结果,我们一个使用的也就2,3个而已 3.1方法多个对象
@Test public void testList1() { Query query = session.createQuery("from Book"); List<Book> list = query.list(); for (Book b : list) { System.out.println(b); } }结果:
Book [bookId=1, bookName=西游记, price=50.0] Book [bookId=2, bookName=红楼梦, price=50.0] Book [bookId=3, bookName=水浒, price=50.0] Book [bookId=4, bookName=三国演义, price=50.0] Book [bookId=5, bookName=斗罗大陆, price=10.0] Book [bookId=6, bookName=洞中强者, price=10.0]3.2返回单个列段,用字符串就可以接收
@Test 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); } }结果:
西游记 红楼梦 水浒 三国演义 斗罗大陆 洞中强者3.3查两个列段及以上,默认返回的是Object【】
@Test 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)); } }结果:
[1, 西游记] [2, 红楼梦] [3, 水浒] [4, 三国演义] [5, 斗罗大陆] [6, 洞中强者]3.4集合(注意map是函数,所以不区分大小写,返回的是map集合)
@Test 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); } }结果:
{0=1, 1=西游记} {0=2, 1=红楼梦} {0=3, 1=水浒} {0=4, 1=三国演义} {0=5, 1=斗罗大陆} {0=6, 1=洞中强者}3.5构造方法(查两个列段及以上,也可返回对象,前提是有对应的构造函数)
@Test 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); } }结果: 查询两个字段,另一个没有查就是null
Book [bookId=1, bookName=西游记, price=null] Book [bookId=2, bookName=红楼梦, price=null] Book [bookId=3, bookName=水浒, price=null] Book [bookId=4, bookName=三国演义, price=null] Book [bookId=5, bookName=斗罗大陆, price=null] Book [bookId=6, bookName=洞中强者, price=null]Hql的占位符是命名参数,不像sql一样一个?,然后就直接赋值 给你们看一个例子: 这里要注意的是:注销的不是错误的,而是其他的赋值方式
@Test public void testList6() { // Query query = session.createQuery("from Book where bookId = :bookId"); // query.setParameter("bookId", 1); // Book b = (Book) query.getSingleResult(); // System.out.println(b); Query query = session.createQuery("from Book where bookId in (:bookIds)"); query.setParameterList("bookIds", new Integer[] {1,2,4}); // List<Integer> params = new ArrayList<Integer>(); // params.add(1); // params.add(2); // params.add(4); // query.setParameterList("bookIds", params); List<Book> list = query.list(); for (Book b : list) { System.out.println(b); } }结果:
Book [bookId=1, bookName=西游记, price=50.0] Book [bookId=2, bookName=红楼梦, price=50.0] Book [bookId=4, bookName=三国演义, price=50.0]这里要提到的就是,两个实体类是需要有关系的才能建立连接查询。 这里我们查询的一个订单表,一订单项,而一个订单有多个订单项,一个订单项只有一个订单,这就是他们的联系。查询的结果是订单的名称,订单项的价格
@Test 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)); } }结果:
[p20, 24] [p20, 25] [p30, 2] [p30, 3] [p30, 4]Hql里面也是有聚合函数的如:sum, avg, max, min, count 这里就举一个例子:
@Test public void testList8() { Query query = session.createQuery("select count(*) from Book"); //getSingleResult 是用来获取单条记录的 Long singleResult = (Long) query.getSingleResult(); System.out.println(singleResult); }结果:6
hql:可以根据方言生成分页语句 * setForstResilt:设置起始下标 * setMaxReults:设置偏移量 一个致命的缺点就是没有查询
@Test 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); } }结果:
Book [bookId=3, bookName=水浒, price=50.0] Book [bookId=4, bookName=三国演义, price=50.0] Book [bookId=5, bookName=斗罗大陆, price=10.0]我们自己来写分页 dao方法
/** * 需求: * 写一个带查询条件的并且能分页方法 * * @param book * @param pagebean * @return */ public List<Book> list1(Book book,PageBean pagebean) { Session session = SessionFactoryUtils.openSession(); Transaction transaction = session.beginTransaction(); List<Book> list = null; String hql = "from Book where 1=1"; String bookName = book.getBookName(); if(StringUtils.isNotBlank(bookName)) { hql += " and bookName like :bookName"; } //query 相当于前面sql所用的preparestatement Query query = session.createQuery(hql); if(StringUtils.isNotBlank(bookName)) { query.setParameter("bookName", bookName); } //通过写上述代码就发现,同样的if判断写了两次 if(pagebean != null && pagebean.isPagination()) { query.setFirstResult(pagebean.getStartIndex()); query.setMaxResults(pagebean.getRows()); } list = query.list(); transaction.commit(); session.close(); return list; }测试代码:
@Test public void testList1() { Book book = new Book(); PageBean pageBean = new PageBean(); //pageBean.setPage(2); book.setBookName("%强%"); List<Book> list1 = this.bookDao.list1(book, pageBean); for (Book b : list1) { System.out.println(b); } }结果:Book [bookId=6, bookName=洞中强者, price=10.0]
上述的到方法的代码有重复的判断,下面我们就对他进行一个改进 写一个baseBao
package com.hu.five.util; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.hibernate.Session; import org.hibernate.query.Query; /** * 1.设置参数的问题 * 2.分页代码重复的问题 * * sql 的通用分页的时候 * getConuntSql(Sql); * select conunt(1) from (sql) t * * getConuntHql(Hql); * hql = "from Book where bookName like :bookName" * hql = "select * from new Book(bid.....) where bookName like :bookName" * select count(1) hql * @author Administrator * */ public class BaseDao { /** * * @param map * @param query */ public void setParam(Map<String, Object> map,Query query) { if(map!=null&&map.size()>0) { Object value = null; Set<Entry<String, Object>> entrySet = map.entrySet(); for (Entry<String, Object> entry : entrySet) { //有时候它并不是单纯的字符串 value = entry.getValue(); //如果是数组 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); } } } } //根据from关键字进行截取,拿到from的下标 public String getConuntSql(String hql) { int index = hql.toUpperCase().indexOf("FROM"); return "select count(*)"+hql.substring(index); } /** * 通用查询方法 * @param session * @param map * @param hql * @param pageBean * @return */ public List executeQuery(Session session,Map<String, Object> map,String hql,PageBean pageBean) { List list = null; if(pageBean!=null&& pageBean.isPagination()) { //拿到counthql String countHql = getConuntSql(hql); //获取query对象 Query createQuery = session.createQuery(countHql); //设置参数 this.setParam(map, createQuery); pageBean.setTotal(createQuery.getSingleResult().toString()); //返回结果集 Query query = session.createQuery(hql); //给预定义hql语句执行对象中的参数赋值,有多少赋值多少 this.setParam(map, query); query.setFirstResult(pageBean.getStartIndex()); query.setMaxResults(pageBean.getRows()); list = query.list(); }else { Query query = session.createQuery(hql); //给预定义hql语句执行对象中的参数赋值,有多少赋值多少 this.setParam(map, query); list = query.list(); } return list; } }dao方法继承BaseDao
public List<Book> list2(Book book,PageBean pagebean) { Session session = SessionFactoryUtils.openSession(); Transaction transaction = session.beginTransaction(); String bookName = book.getBookName(); Map<String, Object> map = new HashMap<>(); String hql = "from Book where 1=1"; if(StringUtils.isNotBlank(bookName)) { hql += " and bookName like :bookName"; map.put("bookName", bookName); } List<Book> list = super.executeQuery(session, map, hql, pagebean); transaction.commit(); session.close(); return list; }测试
@Test public void testList2() { Book book = new Book(); PageBean pageBean = new PageBean(); //pageBean.setPage(2); book.setBookName("%强%"); List<Book> list1 = this.bookDao.list2(book, pageBean); for (Book b : list1) { System.out.println(b); } }结果: Book [bookId=6, bookName=洞中强者, price=10.0]
小编刚刚出道,有什么写的不对的地方就指出来,大家一起进步。有喜欢的就点亮一下旁边的小红心吧,给小编的一个支持。。
