Hibernate(十三):HQL查询(二)
背景
基于上一章节《Hibernate(十二):HQL查询(一)》,已经学习了一部分关于HQL的用法:
- HQL带参数查询
- HQL Order By排序查询
- HQL 设置实体参数查询
本章节将会学习:HQL分页查询、HQL命名语句查询、HQL投影查询、HQL报表查询。
HQL分页查询
1)setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0。默认情况下,Query从查询结果中的第一个对象开始检索。
2)setMaxResults(int maxResults):设定一次最多检索出的对象的数目。默认情况下,Query和Criteria接口检索出查询结果中所有的对象。
1 @Test 2 public void testHQLPageQuery() { 3 String hql = "From Employee"; 4 5 int pageNum = 1; 6 int pageSize = 10; 7 Query query = session.createQuery(hql).setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize); 8 9 List<Employee> employees = query.list(); 10 System.out.println(employees.size()); 11 System.out.println(employees); 12 }
执行sql及结果:
1 Hibernate: 2 select 3 employee0_.ID as ID1_1_, 4 employee0_.NAME as NAME2_1_, 5 employee0_.SALARY as SALARY3_1_, 6 employee0_.EMAIL as EMAIL4_1_, 7 employee0_.DEPARTMENT_ID as DEPARTME5_1_ 8 from 9 DX_EMPLOYEE employee0_ limit ? 10 10 11 [Employee [id=1, name=tommy0, salary=0.0, email=tommy0@dx.com] 12 , Employee [id=2, name=tommy1, salary=1000.0, email=tommy1@dx.com] 13 , Employee [id=3, name=tommy2, salary=2000.0, email=tommy2@dx.com] 14 , Employee [id=4, name=tommy3, salary=3000.0, email=tommy3@dx.com] 15 , Employee [id=5, name=tommy4, salary=4000.0, email=tommy4@dx.com] 16 , Employee [id=6, name=tommy5, salary=5000.0, email=tommy5@dx.com] 17 , Employee [id=7, name=tommy6, salary=6000.0, email=tommy6@dx.com] 18 , Employee [id=8, name=tommy7, salary=7000.0, email=tommy7@dx.com] 19 , Employee [id=9, name=tommy8, salary=8000.0, email=tommy8@dx.com] 20 , Employee [id=10, name=tommy9, salary=9000.0, email=tommy9@dx.com] 21 ]
HQL命名语句查询
在映射文件中定义命名查询语句:
1)Hibernate允许在映射文件中定义字符串形式的查询语句;
2)<query>元素用于定义一个HQL查询语句,它和<class>元素并列;
1 <query name="findNewsByContent"> 2 <![CDATA[From News n Where n.content like :keyword]]> 3 </query>
3)在程序中,通过Session的getNamedQuery()方法获取查询语句对应的Query对象。
修改Employee.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-6-9 23:13:49 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate09.hql01.Employee" table="DX_EMPLOYEE"> 7 。。。 8 </class> 9 <query name="queryWithSalaryScope"> 10 <![CDATA[From Employee e Where e.salary>:minSalary and e.salary<:maxSalary]]> 11 </query> 12 </hibernate-mapping>
测试函数
1 @Test 2 public void testHQLPageQuery() { 3 String hql = "From Employee"; 4 5 int pageNum = 1; 6 int pageSize = 10; 7 Query query = session.createQuery(hql).setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize); 8 9 List<Employee> employees = query.list(); 10 System.out.println(employees.size()); 11 System.out.println(employees); 12 }
执行sql及结果
1 Hibernate: 2 select 3 employee0_.ID as ID1_1_, 4 employee0_.NAME as NAME2_1_, 5 employee0_.SALARY as SALARY3_1_, 6 employee0_.EMAIL as EMAIL4_1_, 7 employee0_.DEPARTMENT_ID as DEPARTME5_1_ 8 from 9 DX_EMPLOYEE employee0_ 10 where 11 employee0_.SALARY>? 12 and employee0_.SALARY<? 13 4 14 [Employee [id=7, name=tommy6, salary=6000.0, email=tommy6@dx.com] 15 , Employee [id=8, name=tommy7, salary=7000.0, email=tommy7@dx.com] 16 , Employee [id=9, name=tommy8, salary=8000.0, email=tommy8@dx.com] 17 , Employee [id=10, name=tommy9, salary=9000.0, email=tommy9@dx.com] 18 ]
HQL投影查询
1)投影查询:查询结果仅包含实体的部分属性。通过SELECT关键字实现。
2)Query的list()方法返回的结果集中包含的是数组类型的元素,每个对象数组代表查询结果的一条记录。
3)可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,是程序代码能完成运用面向对象的语义来访问查询结果集。
4)可以通过DISTINCT关键字来保证查询结果不会返回重复元素。
返回数据测试:
1 @Test 2 public void testHQLFileds() { 3 String hql = "Select e.email,e.salary,e.department From Employee e Where e.salary>:salary and e.department=:department"; 4 Department department = new Department(); 5 department.setId(3); 6 Query query = session.createQuery(hql).setFloat("salary", 10000).setEntity("department", department); 7 8 List<Object[]> result = query.list(); 9 10 for (Object[] item : result) { 11 System.err.println(Arrays.asList(item)); 12 } 13 }
执行sql语句及结果:
1 Hibernate: 2 select 3 employee0_.EMAIL as col_0_0_, 4 employee0_.SALARY as col_1_0_, 5 employee0_.DEPARTMENT_ID as col_2_0_, 6 department1_.ID as ID1_0_, 7 department1_.NAME as NAME2_0_ 8 from 9 DX_EMPLOYEE employee0_ 10 inner join 11 DX_DEPARTMENT department1_ 12 on employee0_.DEPARTMENT_ID=department1_.ID 13 where 14 employee0_.SALARY>? 15 and employee0_.DEPARTMENT_ID=? 16 [tommy12@dx.com, 12000.0, Department [id=3, name=业务部门]] 17 [tommy17@dx.com, 17000.0, Department [id=3, name=业务部门]] 18 [tommy22@dx.com, 22000.0, Department [id=3, name=业务部门]] 19 [tommy27@dx.com, 27000.0, Department [id=3, name=业务部门]] 20 [tommy32@dx.com, 32000.0, Department [id=3, name=业务部门]] 21 [tommy37@dx.com, 37000.0, Department [id=3, name=业务部门]] 22 [tommy42@dx.com, 42000.0, Department [id=3, name=业务部门]] 23 [tommy47@dx.com, 47000.0, Department [id=3, name=业务部门]] 24 [tommy52@dx.com, 52000.0, Department [id=3, name=业务部门]] 25 [tommy57@dx.com, 57000.0, Department [id=3, name=业务部门]] 26 [tommy62@dx.com, 62000.0, Department [id=3, name=业务部门]] 27 [tommy67@dx.com, 67000.0, Department [id=3, name=业务部门]] 28 [tommy72@dx.com, 72000.0, Department [id=3, name=业务部门]] 29 [tommy77@dx.com, 77000.0, Department [id=3, name=业务部门]]
上边我们看到如果返回数据,用起来多少会有点不爽,是可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,是程序代码能完成运用面向对象的语义来访问查询结果集。
修改上边的代码:
1 @Test 2 public void testHQLFileds_() { 3 String hql = "Select new Employee(e.email,e.salary,e.department) From Employee e Where e.salary>:salary and e.department=:department"; 4 Department department = new Department(); 5 department.setId(3); 6 Query query = session.createQuery(hql).setFloat("salary", 10000).setEntity("department", department); 7 8 List<Employee> result = query.list(); 9 10 for (Employee item : result) { 11 System.err.println(item.getId() + "," + item.getEmail() + "," + item.getSalary() + "," + item.getDepartment()); 12 } 13 }
执行sql及结果:
1 Hibernate: 2 select 3 employee0_.EMAIL as col_0_0_, 4 employee0_.SALARY as col_1_0_, 5 employee0_.DEPARTMENT_ID as col_2_0_ 6 from 7 DX_EMPLOYEE employee0_ 8 inner join 9 DX_DEPARTMENT department1_ 10 on employee0_.DEPARTMENT_ID=department1_.ID 11 where 12 employee0_.SALARY>? 13 and employee0_.DEPARTMENT_ID=? 14 Hibernate: 15 select 16 department0_.ID as ID1_0_0_, 17 department0_.NAME as NAME2_0_0_ 18 from 19 DX_DEPARTMENT department0_ 20 where 21 department0_.ID=? 22 null,tommy12@dx.com,12000.0,Department [id=3, name=业务部门] 23 null,tommy17@dx.com,17000.0,Department [id=3, name=业务部门] 24 null,tommy22@dx.com,22000.0,Department [id=3, name=业务部门] 25 null,tommy27@dx.com,27000.0,Department [id=3, name=业务部门] 26 null,tommy32@dx.com,32000.0,Department [id=3, name=业务部门] 27 null,tommy37@dx.com,37000.0,Department [id=3, name=业务部门] 28 null,tommy42@dx.com,42000.0,Department [id=3, name=业务部门] 29 null,tommy47@dx.com,47000.0,Department [id=3, name=业务部门] 30 null,tommy52@dx.com,52000.0,Department [id=3, name=业务部门] 31 null,tommy57@dx.com,57000.0,Department [id=3, name=业务部门] 32 null,tommy62@dx.com,62000.0,Department [id=3, name=业务部门] 33 null,tommy67@dx.com,67000.0,Department [id=3, name=业务部门] 34 null,tommy72@dx.com,72000.0,Department [id=3, name=业务部门] 35 null,tommy77@dx.com,77000.0,Department [id=3, name=业务部门]
HQL报表查询
报表查询用于对数据分组和统计,与SQL一样,HQL利用GROUP BY关键字对数据分组,用HAVING关键字对分组数据设定约束条件。
在HQL查询语句中可以调用以下聚合函数:
- count()
- min()
- max()
- sum()
- avg()
测试代码
@Test public void testGroupBy() { String hql = "Select min(e.salary),max(e.salary) " + "From Employee e " + "group by e.department having(min(e.salary)>:minSalary)"; Query query = session.createQuery(hql).setFloat("minSalary", 0); List<Object[]> result = query.list(); for (Object[] item : result) { System.out.println(Arrays.asList(item)); } }
执行sql与结果
1 Hibernate: 2 select 3 min(employee0_.SALARY) as col_0_0_, 4 max(employee0_.SALARY) as col_1_0_ 5 from 6 DX_EMPLOYEE employee0_ 7 group by 8 employee0_.DEPARTMENT_ID 9 having 10 min(employee0_.SALARY)>? 11 [1000.0, 76000.0] 12 [2000.0, 77000.0] 13 [3000.0, 78000.0] 14 [4000.0, 79000.0]
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。