单表查询:
Hibernate是DAO层技术,对数据的使用,查询是最为重要的。Hibernate的查询技术非常强大,支持原始SQL语句查询,支持QBC查询及Hibernate特有的HQL查询。
HQL,Hibernate Query Language,Hibernate查询语言,它与SQL非常相似。但,HQL是面向对象的查询语言,而SQL是面向二维表的。HQL查询语句中使用的是类名与属性名,而SQL语句使用的是表名与字段名。
QBC,Query By Criteria,标准查询,一种比HQL更为面向对象的查询方法。
对应API:
(1) Query接口:
Hibernate进行HQL查询的接口,支持动态绑定参数的功能。使用Session对象的createQuery方法可获取Query对象。
Query query = session.createQuery(hql);
(2)SQLQuery接口:
Hibernate进行SQL原生查询的接口,支持动态绑定参数的功能,是Query接口的子接口。使用Session对象的createSQLQuery()方法可获取SQLQuery对象。
SQLQuery sqlQuery = session.createSQLQuery(sql);
其查询出的结果对象默认为Object,当然,若结果为List,则其元素为Object。使用SQLQuery的addEntity(Xxx.class)方法,可以将其结果泛型设定为指定类型。
(3) Criteria接口:
Criteria,标准、准则,Hibernate进行Criteria查询的接口,与Query接口无关。使用Session对象的createCriteria()方法可获取Criteria对象。
Criteria criteria = session.createCriteria(Xxx.class);
具体查询代码:
(1) 查询所有:
1 //查询所有 2 @Test 3 public void test01_SQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String sql = "select tid,tname,tage,tscore from t_student"; 11 List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).list(); 12 for (Student student : list) { 13 System.out.println(student); 14 } 15 //4. 事务提交 16 session.getTransaction().commit(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 //5. 事务回滚 20 session.getTransaction().rollback(); 21 } 22 } 23 24 @Test 25 public void test01_HQL() { 26 //1. 获取Session 27 Session session = HbnUtils.getSession(); 28 try { 29 //2. 开启事务 30 session.beginTransaction(); 31 //3. 操作 32 //sql中出现的是表名与字段名,hql中出现的是类名与属性名 33 String hql = "from Student"; 34 List<Student> list = session.createQuery(hql).list(); 35 for (Student student : list) { 36 System.out.println(student); 37 } 38 //4. 事务提交 39 session.getTransaction().commit(); 40 } catch (Exception e) { 41 e.printStackTrace(); 42 //5. 事务回滚 43 session.getTransaction().rollback(); 44 } 45 } 46 47 @Test 48 public void test01_QBC() { 49 //1. 获取Session 50 Session session = HbnUtils.getSession(); 51 try { 52 //2. 开启事务 53 session.beginTransaction(); 54 //3. 操作 55 List<Student> list = session.createCriteria(Student.class).list(); 56 for (Student student : list) { 57 System.out.println(student); 58 } 59 //4. 事务提交 60 session.getTransaction().commit(); 61 } catch (Exception e) { 62 e.printStackTrace(); 63 //5. 事务回滚 64 session.getTransaction().rollback(); 65 } 66 }
(2)对查询结果排序:
1 //查询结果查询 2 @Test 3 public void test02_SQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String sql = "select tid,tname,tage,tscore from t_student order by tage desc"; 11 List<Student> list = session.createSQLQuery(sql).addEntity(Student.class).list(); 12 for (Student student : list) { 13 System.out.println(student); 14 } 15 //4. 事务提交 16 session.getTransaction().commit(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 //5. 事务回滚 20 session.getTransaction().rollback(); 21 } 22 } 23 24 @Test 25 public void test02_HQL() { 26 //1. 获取Session 27 Session session = HbnUtils.getSession(); 28 try { 29 //2. 开启事务 30 session.beginTransaction(); 31 //3. 操作 32 String hql = "from Student order by age desc"; 33 List<Student> list = session.createQuery(hql).list(); 34 for (Student student : list) { 35 System.out.println(student); 36 } 37 //4. 事务提交 38 session.getTransaction().commit(); 39 } catch (Exception e) { 40 e.printStackTrace(); 41 //5. 事务回滚 42 session.getTransaction().rollback(); 43 } 44 } 45 46 @Test 47 public void test02_QBC() { 48 //1. 获取Session 49 Session session = HbnUtils.getSession(); 50 try { 51 //2. 开启事务 52 session.beginTransaction(); 53 //3. 操作 54 List<Student> list = session.createCriteria(Student.class).addOrder(Order.desc("age")).list(); 55 for (Student student : list) { 56 System.out.println(student); 57 } 58 //4. 事务提交 59 session.getTransaction().commit(); 60 } catch (Exception e) { 61 e.printStackTrace(); 62 //5. 事务回滚 63 session.getTransaction().rollback(); 64 } 65 }
(3) 动态参数绑定查询:
1 //动态参数绑定查询 2 @Test 3 public void test03_1() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "from Student where age > ? and score < ?"; 11 List<Student> list = session.createQuery(hql) 12 .setInteger(0, 20) 13 .setDouble(1, 94) 14 .list(); 15 for (Student student : list) { 16 System.out.println(student); 17 } 18 //4. 事务提交 19 session.getTransaction().commit(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 //5. 事务回滚 23 session.getTransaction().rollback(); 24 } 25 } 26 27 @Test 28 public void test03_2() { 29 //1. 获取Session 30 Session session = HbnUtils.getSession(); 31 try { 32 //2. 开启事务 33 session.beginTransaction(); 34 //3. 操作 35 String hql = "from Student where age > :myage and score < :myscore"; 36 List<Student> list = session.createQuery(hql) 37 .setInteger("myage", 20) 38 .setDouble("myscore", 94) 39 .list(); 40 for (Student student : list) { 41 System.out.println(student); 42 } 43 //4. 事务提交 44 session.getTransaction().commit(); 45 } catch (Exception e) { 46 e.printStackTrace(); 47 //5. 事务回滚 48 session.getTransaction().rollback(); 49 } 50 } 51 52 @Test 53 public void test03_3() { 54 //1. 获取Session 55 Session session = HbnUtils.getSession(); 56 try { 57 //2. 开启事务 58 session.beginTransaction(); 59 //3. 操作 60 String hql = "from Student where age > ? and score < ?"; 61 List<Student> list = session.createSQLQuery(hql) 62 .setParameter(0, 20) 63 .setParameter(1, 94.0) //这里必须是94.0 64 .list(); 65 for (Student student : list) { 66 System.out.println(student); 67 } 68 //4. 事务提交 69 session.getTransaction().commit(); 70 } catch (Exception e) { 71 e.printStackTrace(); 72 //5. 事务回滚 73 session.getTransaction().rollback(); 74 } 75 } 76 77 @Test 78 public void test03_4() { 79 //1. 获取Session 80 Session session = HbnUtils.getSession(); 81 try { 82 //2. 开启事务 83 session.beginTransaction(); 84 //3. 操作 85 String hql = "from Student where age > :myage and score < :myscore"; 86 List<Student> list = session.createQuery(hql) 87 .setParameter("myage", 20) 88 .setParameter("myscore", 94.0) //这里必须是94.0 89 .list(); 90 for (Student student : list) { 91 System.out.println(student); 92 } 93 //4. 事务提交 94 session.getTransaction().commit(); 95 } catch (Exception e) { 96 e.printStackTrace(); 97 //5. 事务回滚 98 session.getTransaction().rollback(); 99 } 100 }
(4) 分页查询:
//分页查询 @Test public void test04_SQL() { //1. 获取Session Session session = HbnUtils.getSession(); try { //2. 开启事务 session.beginTransaction(); //3. 操作 String sql = "select * from t_student limit ?,?"; List<Student> list = session.createSQLQuery(sql) .addEntity(Student.class) .setInteger(0, 4) .setInteger(1, 3) .list(); for (Student student : list) { System.out.println(student); } //4. 事务提交 session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); //5. 事务回滚 session.getTransaction().rollback(); } } @Test public void test04_HQL() { //1. 获取Session Session session = HbnUtils.getSession(); try { //2. 开启事务 session.beginTransaction(); //3. 操作 String hql = "from Student"; List<Student> list = session.createQuery(hql) .setFirstResult(4) .setMaxResults(3) .list(); for (Student student : list) { System.out.println(student); } //4. 事务提交 session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); //5. 事务回滚 session.getTransaction().rollback(); } }
(5) 模糊查询:
1 //模糊查询 2 @Test 3 public void test05_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "from Student where name like :myname"; 11 List<Student> list = session.createQuery(hql) 12 .setString("myname", "%n%") 13 .list(); 14 for (Student student : list) { 15 System.out.println(student); 16 } 17 //4. 事务提交 18 session.getTransaction().commit(); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 //5. 事务回滚 22 session.getTransaction().rollback(); 23 } 24 }
(6) 唯一性查询:
1 //唯一性查询 2 @Test 3 public void test06_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "from Student where id=:myid"; 11 Student student = (Student) session.createQuery(hql) 12 .setInteger("myid", 3) 13 .uniqueResult(); 14 System.out.println(student); 15 //4. 事务提交 16 session.getTransaction().commit(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 //5. 事务回滚 20 session.getTransaction().rollback(); 21 } 22 }
(7) 聚合函数查询:
1 //聚合函数查询 2 @Test 3 public void test07_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "select count(id) from Student"; 11 Long count = (Long) session.createQuery(hql).uniqueResult(); 12 System.out.println(count); 13 //4. 事务提交 14 session.getTransaction().commit(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 //5. 事务回滚 18 session.getTransaction().rollback(); 19 } 20 }
(8) 投影查询:
1 //投影查询 2 @Test 3 public void test08_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "select new Student(name, age) from Student"; 11 List<Student> list = session.createQuery(hql).list(); 12 for (Student student : list) { 13 System.out.println(student); 14 } 15 //4. 事务提交 16 session.getTransaction().commit(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 //5. 事务回滚 20 session.getTransaction().rollback(); 21 } 22 }
(9) 分组查询:
1 //分组查询 2 @Test 3 public void test09_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 String hql = "from Student group by age"; 11 List<Integer> list = session.createQuery(hql).list(); //每个年龄段的第一个人 12 System.out.println(list); 13 14 String hql2 = "select age from Student group by age"; 15 List<Integer> list2 = session.createQuery(hql2).list(); //共有几个年龄段 16 System.out.println(list2); 17 18 String hql3 = "select age from Student group by age having count(age) > 1"; 19 List<Integer> list3 = session.createQuery(hql3).list(); //人数多于1人的年龄段 20 System.out.println(list3); 21 //4. 事务提交 22 session.getTransaction().commit(); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 //5. 事务回滚 26 session.getTransaction().rollback(); 27 } 28 }
(10) iterator和N+1问题的解决:
1 @Test 2 public void test10_3() { 3 //1. 获取Session 4 Session session = HbnUtils.getSession(); 5 try { 6 //2. 开启事务 7 session.beginTransaction(); 8 //3. 操作 9 //第一次查询 10 String hql = "from Student"; 11 List<Student> list = session.createQuery(hql).list(); 12 for (Student student : list) { 13 System.out.println(student); 14 } 15 //第二次查询 16 String hql2 = "from Student"; 17 Iterator<Student> it2 = session.createQuery(hql2).iterate(); 18 while (it2.hasNext()) { 19 Student student2 = it2.next(); 20 System.out.println(student2); 21 } 22 //4. 事务提交 23 session.getTransaction().commit(); 24 } catch (Exception e) { 25 e.printStackTrace(); 26 //5. 事务回滚 27 session.getTransaction().rollback(); 28 } 29 }
解释:list()方法对所有Student表的每条数据进行一次详情查询,但是第二次再用list()查询时不会从Session缓存中读取数据;
而iterator()方法首先对Student表的主键进行查询(对主键的查询比详情效率高,因为数据库中存在索引),再根据主键依次对Student表中的每条数据进行逐个查询,总共查询了N+1次,但是第二次再用iterator()查询时,只会做主键查询,然后根据主键从Session缓存中读取数据,而不会进行详情查询。
所以,如果要进行多次查询时,第一次使用list()查询,之后每次都使用iterator()查询。
(11) 命名查询(好处:可以在配置文件中修改查询语句):
1 //命名查询 2 @Test 3 public void test11_HQL() { 4 //1. 获取Session 5 Session session = HbnUtils.getSession(); 6 try { 7 //2. 开启事务 8 session.beginTransaction(); 9 //3. 操作 10 Student student = (Student) session.getNamedQuery("selectById") 11 .setInteger("myid", 3) 12 .uniqueResult(); 13 System.out.println(student); 14 //4. 事务提交 15 session.getTransaction().commit(); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 //5. 事务回滚 19 session.getTransaction().rollback(); 20 } 21 }
对应映射文件为:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping> 7 <!-- 类到表的映射,属性到字段的映射 --> 8 <class name="com.tongji.beans.Student" table="t_student"> 9 <id name="id" column="tid"> 10 <generator class="native"/> 11 </id> 12 <property name="name" column="tname"/> 13 <property name="age" column="tage"/> 14 <property name="score" column="tscore"/> 15 </class> 16 <query name="selectById">from Student where id=:myid</query> 17 </hibernate-mapping>