一、HQL 检索方式

以双向的一对多来测试 HQL 检索方式。以 Department 和 Employee 为例。

建表语句:

CREATE TABLE department
(
dept_id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
dept_name VARCHAR(50)
);
CREATE INDEX FK_8hf3vewo7w3v9doungcc51wwy ON department (dept_id);
CREATE TABLE employee
(
emp_id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
emp_name VARCHAR(50),
salary FLOAT,
dept_id_fk INT(11),
CONSTRAINT FK_miun1wlqp4ujpsgfshyfi7g9j FOREIGN KEY (dept_id_fk) REFERENCES department (dept_id)
);
CREATE INDEX FK_miun1wlqp4ujpsgfshyfi7g9j ON employee (dept_id_fk);

对应的实体和 hbm 文件

public class Department {
private Integer deptId;
private String deptName;
private Set<Employee> emps = new HashSet<>();
}
public class Employee {
private Integer empId;
private String empName;
private Float salary;
private Department dept;
}
<hibernate-mapping>
<class name="com.solverpeng.hql.Department" table="department" schema="hibernate">
<id name="deptId" column="dept_id">
<generator class="native"/>
</id>
<property name="deptName" column="dept_name"/>
<set name="emps" inverse="true">
<key>
<column name="dept_id_fk"/>
</key>
<one-to-many not-found="ignore" class="com.solverpeng.hql.Employee"/>
</set>
</class>
</hibernate-mapping>

Department.hbm.xml

<hibernate-mapping>

    <class name="com.solverpeng.hql.Employee" table="employee" schema="hibernate">
<id name="empId" column="emp_id">
<generator class="native"/>
</id>
<property name="empName" column="emp_name"/>
<property name="salary" column="salary"/>
<many-to-one name="dept" class="com.solverpeng.hql.Department">
<column name="dept_id_fk"/>
</many-to-one>
</class>
<query name="findAllEmployees">
<![CDATA[
from Employee
]]>
</query>
</hibernate-mapping>

Employee.hbm.xml

1.在查询语句中设定各种查询条件

@Test
public void testHql(){
Department dept = new Department();
dept.setDeptId(7); List<Employee> list = session.createQuery("FROM Employee e where e.empName like ? and e.empId > ? and dept = ? order by e.empId " +
"desc ")
.setString(0, "%b%").setInteger(1, 3).setEntity(2, dept).list(); for(Employee employee : list) {
System.out.println(employee);
} }

说明:

(1)通过 Session 的 createQuery(hql) 方法创建一个 Query 对象,hql 支持动态绑定参数。调用 Query 的相关方法执行查询。

(2)Query 接口支持链式操作,它的 setXxx() 方法返回自身实例。

(3)方法 setEntity(obj),obj 只需要绑定一个 id 就可以。

(4)支持 order by 排序。

(5)参数的位置从 0 开始。

@Test
public void testHqlNamed() {
List<Employee> list = session.createQuery("from Employee e where e.empName like :name and e.empId > :id and e.dept = ?")
.setString("name", "%a%").setInteger("id", 1).list();
for(Employee employee : list) {
System.out.println(employee);
}
}

说明:

(1)支持按照参数名字查询,定义的参数名以 ":" 开头。

2.查询对象的部分属性(查询结果仅包含实体的部分属性)

@Test
public void testPropertyQuery() {
Department dept = new Department();
dept.setDeptId(7);
List<Object[]> list = session.createQuery("select empName, empId from Employee where dept = ?").setEntity(0, dept).list();
for(Object[] objects : list) {
System.out.println(Arrays.asList(objects));
}
}

说明:

(1)这种情况下查询出来的是一个 Object[] 数组类型。

@Test
public void testPropertyQuery2() {
Department dept = new Department();
dept.setDeptId(7);
List<Employee> list = session.createQuery("select new Employee (empId, empName) from Employee where dept = ?").setEntity(0, dept)
.list();
for(Employee employee : list) {
System.out.println(employee);
}
}

(1)查询出来的是 Employee 类型

(2)需要在 Employee 实体类中定义相应的构造器,注意顺序。同时添加一个无参的构造器。

(3)可以通过 Distinct 关键字来去重。

3.分页查询

@Test
public void testHqlPage() {
int pageNo = 2;
int pageSize = 3; List<Employee> list = session.createQuery("from Employee").setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();
for(Employee employee : list) {
System.out.println(employee);
} }

(1)setFirstResult(int firstResult):设定从哪一个对象开始检索。

(2)setMaxResults(int maxResult) : 设定每次检索多少条记录。

4.命名查询(很少用到)

@Test
public void testNamedQuery() {
int pageNo = 3;
int pageSize = 5;
List<Employee> employees = session.getNamedQuery("findAllEmployees").setFirstResult((pageNo - 1) * pageSize).setMaxResults(
pageSize).list();
for(Employee employee : employees) {
System.out.println(employee);
}
}

说明:

(1)其中 findAllEmployees 定义在了 Employee.hbm.xml 文件中,用 <query>元素来定义,和 class 节点并列。

(2)通过 Session 的 getNamedQuery() 方法获取对应的 Query 对象。

5.聚集函数和分组查询

@Test
public void testFunction() {
List<Object[]> salary =
session.createQuery("select dept.deptName, min(salary), max(salary) from Employee group by dept HAVING min(salary) > :salary")
.setFloat("salary", 4000).list();
for(Object[] objects : salary) {
System.out.println(Arrays.asList(objects));
}
}

说明:

(1)通过 GROUP BY 进行分组,通过 HAVING 对分组数据设定约束条件。

(2)可以调用的聚集函数:count() 、min()、max()、sum()、avg()

6.迫切左外链接和左外链接

(1)迫切左外链接

@Test
public void testHqlFetch() {
List list = session.createQuery("from Department d left join fetch d.emps").list();
}

打印 SQL:

Hibernate: 
    select
        department0_.dept_id as dept1_0_0_,
        emps1_.emp_id as emp1_1_1_,
        department0_.dept_name as dept2_0_0_,
        emps1_.emp_name as emp2_1_1_,
        emps1_.salary as salary3_1_1_,
        emps1_.dept_id_fk as dept4_1_1_,
        emps1_.dept_id_fk as dept4_0_0__,
        emps1_.emp_id as emp1_1_0__
    from
        hibernate.department department0_
    left outer join
        hibernate.employee emps1_
            on department0_.dept_id=emps1_.dept_id_fk

说明:

  • 同时查询了 Employee 对象
  • list() 方法返回的集合存放的实体对象的引用,每个 Department 关联的 Employee 集合都被初始化。
  • 可以通过 distinct 关键字去重,也可以通过一个 HashSet() 去重(new ArrayList<>(new LinkedHashSet(depts)))。
  • 此种情况下,会忽略配置文件中检索策略。

(2)左外链接

@Test
public void testHqlLeftJoin2() {
List<Object[]> list = session.createQuery("from Department d left join d.emps").list();
for(Object[] objects : list) {
System.out.println(Arrays.asList(objects));
}
}
Hibernate:
select
department0_.dept_id as dept1_0_0_,
emps1_.emp_id as emp1_1_1_,
department0_.dept_name as dept2_0_0_,
emps1_.emp_name as emp2_1_1_,
emps1_.salary as salary3_1_1_,
emps1_.dept_id_fk as dept4_1_1_
from
hibernate.department department0_
left outer join
hibernate.employee emps1_
on department0_.dept_id=emps1_.dept_id_fk

说明:

  • list() 方法返回的集合中存放的是对象数组类型。
  • 根据配置文件来决定 Employee 集合的初始化时机。

7.迫切内连接和内连接

(1)迫切内连接(inner join fetch),与迫切左外链接类似,查询的时候同时将关联的另一端的对象进行了初始化。

(2)内连接(inner join),与左外链接类似,查询的时候是根据配置文件中的检索策略来决定另一端初始化的时机。

8.小结

(1)如果在 HQL 中没有显式的指定检索策略,则使用配置文件中的检索策略。

(2)HQL 会忽略配置文件中设置的迫切左外链接检索策略,若想 HQL 采用迫切左外链接策略,就必须在 HQL 语句中显式的指定它。

二、QBC 检索方式

1.设定各种查询条件

(1)like、gt、排序

@Test
public void testQBC() {
Criteria criteria = session.createCriteria(Employee.class); criteria.add(Restrictions.like("empName", "a", MatchMode.ANYWHERE));
criteria.add(Restrictions.gt("salary", 1000F));
// 排序
criteria.addOrder(Order.desc("salary")); List list = criteria.list();
System.out.println(list);
}
Hibernate:
select
this_.emp_id as emp1_1_0_,
this_.emp_name as emp2_1_0_,
this_.salary as salary3_1_0_,
this_.dept_id_fk as dept4_1_0_
from
hibernate.employee this_
where
this_.emp_name like ?
and this_.salary>?
order by
this_.salary desc

(2)and、or

public void testQbc2() {
Criteria criteria = session.createCriteria(Employee.class); Conjunction conjunction = Restrictions.conjunction();
conjunction.add(Restrictions.like("empName", "a", MatchMode.ANYWHERE));
Department department = new Department();
department.setDeptId(6);
conjunction.add(Restrictions.eq("dept", department)); Disjunction disjunction = Restrictions.disjunction();
disjunction.add(Restrictions.gt("salary", 1000F));
disjunction.add(Restrictions.lt("salary", 20000F)); criteria.add(conjunction).add(disjunction); criteria.list(); }
Hibernate:
select
this_.emp_id as emp1_1_0_,
this_.emp_name as emp2_1_0_,
this_.salary as salary3_1_0_,
this_.dept_id_fk as dept4_1_0_
from
hibernate.employee this_
where
(
this_.emp_name like ?
and this_.dept_id_fk=?
)
and (
this_.salary>?
or this_.salary<?
)

2.分页查询

@Test
public void testQbc4() {
Criteria criteria = session.createCriteria(Employee.class);
// 分页
int pageNo = 2;
int pageSize = 4;
List<Employee> list = criteria.setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();
}
Hibernate:
select
this_.emp_id as emp1_1_0_,
this_.emp_name as emp2_1_0_,
this_.salary as salary3_1_0_,
this_.dept_id_fk as dept4_1_0_
from
hibernate.employee this_ limit ?,
?

3.聚集函数查询

@Test
public void testQbc3() {
Criteria criteria = session.createCriteria(Employee.class);
criteria.setProjection(Projections.max("salary")); String maxSalary = criteria.uniqueResult().toString();
System.out.println(maxSalary);
}
Hibernate:
select
max(this_.salary) as y0_
from
hibernate.employee this

4.小结

(1)创建 QBC 查询:session.createCriteria()

(2)like 关键字:Restrictions.like(),MatchMode.ANYWHERE

(3)排序:criteria.addOrder(),Order.desc、Order.asc

(4)AND:Conjunction conjunction = Restrictions.conjunction()

(5)Or : Disjunction disjunction = Restrictions.disjunction()

(6)聚集函数:criteria.setProjection(Projections.max("salary"))

(7)查询单个对象:criteria.uniqueResult()

(8)查询对象列表:criteria.list()

三、本地 SQL

@Test
public void testNativeSql() {
Employee employee = new Employee();
employee.setEmpId(5);
String empName = (String) session.createSQLQuery("SELECT emp_name FROM employee where emp_id = ?")
.setEntity(0, employee).uniqueResult();
System.out.println(empName);
}
Hibernate:
SELECT
emp_name
FROM
employee
where
emp_id = ?
bb2

通过 session.createSQLQuery() 方法来创建本地 SQL 查询对象。

四、HQL 的更新操作

@Test
public void testHqlUpdate() {
session.createQuery("delete from Employee where empId = ?").setInteger(0, 13).executeUpdate();
}
Hibernate:
delete
from
hibernate.employee
where
emp_id=?

五、总结

介绍了 HQL、QBC、本地SQL查询。查询对象都是通过 Session 来创建的。依次为:session.createQuery()、session.createCriteria()、session.createSQLQuery()。

其中 QBC 提供了比 HQL 更为彻底的,更加面向 Java 编程风格的一种方式。在学习 HQL 的时候,需要重点关注迫切左外链接。本地化查询作为对 HQL 的一种补充。

学习的时候,注意对比学习。

更多内容请参看:documentation/manual/en-US/html_single/index.html

Hibernate —— HQL、QBC检索方式的更多相关文章

  1. Hibernate的QBC检索方式

    Hibernate的QBC检索方式 一直习惯了Hibernate的HQL查询,一直也觉得挺方便,对于最近项目里出现的QBC(org.hibernate.Criteria接口)也是报着一种看看的心理,因 ...

  2. hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

    hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 ...

  3. Hibernate之QBC检索和本地SQL检索

    QBC查询就是通过使用Hibernate提供的Query By Criteria API来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口 本地SQL查询来完善HQL ...

  4. HQL的检索方式

    HQL是面向持久化类的,所以需要查询表的字段都要用持久化类指定例如 String hql = "SELECT e.email, e.salary, e.dept FROM Employee ...

  5. 【Hibernate】检索方式

    一.概述 二.HQL 2.1 简介 2.2 查询所有记录 2.3 查询使用别名 2.4 排序 2.5 分页查询 2.6 单个对象查询 2.7 参数绑定 2.8 投影操作 2.9 模糊查询 2.10 S ...

  6. Hibernate之检索方式

    时间:2017-1-22 16:09 --检索方式Hibernate中提供了以下几种检索对象的方式:    *   导航对象图检索方式        根据已经加载额对象导航到其他对象.        ...

  7. [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. Hibernate -- 检索方式 HQL

    Hibernate 提供了以下几种检索对象的方式 导航对象图检索方式:  根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的OID 来检索对象 HQL 检索方式:使用面向对象的HQL查询 ...

  9. Hibernate的检索方式

    Hibernate的检索方式 检索方式(查询的方式) 导航对象图检索方式: 根据已经加载的对象导航到其他对象 Customer customer = (Customer)session.get(Cus ...

随机推荐

  1. linux用户管理(二)

    最简单的加入用户useradd 用户名这样的命令不好,因为会新建一个组为这个用户. 这里提到一个问题,为什么普通用户没有/etc/shadow的写权限却能修改自己的密码呢. 因为 /user/bin/ ...

  2. VB.net 2010下关联与程序图标设置

    '*************************************************************************'**模 块 名:VB.net 2010下关联与程序 ...

  3. C#如何测试代码运行时间

    1.System.Diagnostics.Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 开始监视代码运行时间 // 需要测试 ...

  4. IOS_反射

    // // PJReflect.m // 新浪微博 // // Created by pj on 14-8-8. // Copyright (c) 2014年 pj. All rights reser ...

  5. SQL Server2016 原生支持JSON

    SQL Server2016 原生支持JSON SQL Server 2005 开始支持 XML 数据类型,提供原生的 XML数据类型.XML 索引以及各种管理 XML 或输出 XML 格式的函数. ...

  6. 【Java并发编程实战】-----synchronized

    在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...

  7. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3) 到上一篇为止,拾取一个VBO里的单个图元的问题已经彻底解决了.那么来看下一个问题:一个场景里可能会有多个VBO,此时每个 ...

  8. ASP.NET MVC 从零开始 - create and run

    这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 如果你想用 ASP.NET MVC 创建一个网络应用,那么你可以搜到很多的文章.但是没有多少文章告诉你 ...

  9. Uiautomator 2.0之UiWatcher类学习小记

    1. 主要功能 使用此方法可以处理中断问题,从而保证测试用例的正常运行. 2. 相关API API 说明 registerWatcher (String name, UiWatcher watcher ...

  10. BFC,定位,浮动,7种垂直居中方法

    目录 一.BFC与IFC 1.1.BFC与IFC概要 1.2.如何产生BFC 1.3.BFC的作用与特点 二.定位 2.2.relative 2.3.absolute 2.4.fixed 2.5.z- ...