Hibernate(十三):HQL查询

Posted yy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate(十三):HQL查询相关的知识,希望对你有一定的参考价值。

背景

基于上一章节《Hibernate(十二):HQL查询(一)》,已经学习了一部分关于HQL的用法:

  1. HQL带参数查询
  2. HQL Order By排序查询
  3. 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查询语句中可以调用以下聚合函数:

  1. count()
  2. min()
  3. max()
  4. sum()
  5. 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]

 

以上是关于Hibernate(十三):HQL查询的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate的HQL多表查询

Hibernate(十三)迫切内连接fetch

Hibernate命名查询

Hibernate HQL中的子查询

转: Hibernate HQL查询 插入 更新(update)实例

Hibernate HQL查询语句总结