背景

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

  1. HQL带参数查询
  2. HQL Order By排序查询
  3. HQL 设置实体参数查询
  4. HQL分页查询
  5. HQL命名语句查询
  6. HQL投影查询
  7. HQL报表查询

本章节将会学习:HQL(迫切)左外连接、HQL(迫切)内连接、总结关联级别运行时的检索策略。

HQL(迫切)左外连接

 迫切左外连接

1)LEFT JOIN FETCH 关键字表示迫切左外连接检索策略

2)list()方法返回的集合中存放实体对象的引用,每个Department对象关联的Employee结合都被初始化,存放所有关联的Employee的实体对象

3)查询结果中可能会被包含重复的元素,可以通过HashSet来过滤重复元素,也可以在hql语句中使用distinct.

测试代码:

     @Test
public void testLeftJoinFetch() {
String hql = "FROM Department d LEFT JOIN FETCH d.employees";
List<Department> departs = session.createQuery(hql).list(); System.out.println("直接左外连接查询结果集合个数:" + departs.size());
Department depart = departs.get(0);
System.out.println("直接左外连接查询结果集的第一个元素Department Name:" + depart.getName() + ",该department的Employees个数:" + depart.getEmployees().size()); departs = new ArrayList<>(new LinkedHashSet<>(departs));
System.out.println("使用LinkedHashSet排除重复项后集合个数:" + departs.size()); hql = "Select Distinct d FROM Department d LEFT JOIN FETCH d.employees";
List<Department> departs2 = session.createQuery(hql).list();
System.out.println("使用Distinct排除重复项后集合个数:" + departs2.size());
for(Department department : departs2){
System.out.println("使用Distinct排除重复项后元素Department Name:" + department.getName() + ",该department的Employees个数:" + department.getEmployees().size());
}
}

执行sql及结果:

 Hibernate:
select
department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
employees1_.ID as ID1_1_0__
from
DX_DEPARTMENT department0_
left outer join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
直接左外连接查询结果集合个数:80
直接左外连接查询结果集的第一个元素Department Name:开发部门,该department的Employees个数:16
使用LinkedHashSet排除重复项后集合个数:5
Hibernate:
select
distinct department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
employees1_.ID as ID1_1_0__
from
DX_DEPARTMENT department0_
left outer join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
使用Distinct排除重复项后集合个数:5
使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

左外连接

1)LEFT JOIN 关键字表示左外连接查询

2)list()方法返回的集合中存放的是数组类型

3)根据配置文件来决定Employee集合的策略(以下测试代码,前提是employee.hbm.xml中没有配置join='fetch'策略)

4)如果希望list()方法返回的集合中仅包含Department对象,可以在HQL查询语句中使用SELECT关键字。

测试代码:

     @Test
public void testLeftJoin() {
String hql = "FROM Department d LEFT JOIN d.employees";
List<Department> departs = session.createQuery(hql).list(); System.out.println("直接左外连接查询结果集合个数:" + departs.size());
// 将会抛出异常:
//Department depart = departs.get(0);
//System.out.println("直接左外连接查询结果集的第一个元素Department Name:" + depart.getName() + ",该department的Employees个数:" + depart.getEmployees().size()); // 排重无效
departs = new ArrayList<>(new LinkedHashSet<>(departs));
System.out.println("使用LinkedHashSet排除重复项后集合个数:" + departs.size()); hql = "Select Distinct d FROM Department d LEFT JOIN d.employees";
List<Department> departs2 = session.createQuery(hql).list();
System.out.println("使用Distinct排除重复项后集合个数:" + departs2.size());
for(Department department : departs2){
System.out.println("使用Distinct排除重复项后元素Department Name:" + department.getName() + ",该department的Employees个数:" + department.getEmployees().size());
}
}

执行sql及结果

 Hibernate:
select
department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_DEPARTMENT department0_
left outer join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
直接左外连接查询结果集合个数:80
使用LinkedHashSet排除重复项后集合个数:80
Hibernate:
select
distinct department0_.ID as ID1_0_,
department0_.NAME as NAME2_0_
from
DX_DEPARTMENT department0_
left outer join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
使用Distinct排除重复项后集合个数:5
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

HQL(迫切)内连接

 迫切内连接

1)INNER JOIN FETCH关键字表示迫切内连接,也可以省略INNER关键字

2)list()方法返回的集合中存放Department对象的引用,每个Department对象的Employee集合都被初始化,存放所有关联的Employee对象。

测试函数:

     @Test
public void testInnerJoinFetch() {
// // 先执行追加employee一条记录。
// Employee employee = new Employee("name", 10000, "email@test.com");
// session.save(employee);
// Department department = new Department("党政部门");
// session.save(department); String hql = "FROM Department d INNER JOIN FETCH d.employees";
List<Department> departs = session.createQuery(hql).list(); System.out.println("直接左外连接查询结果集合个数:" + departs.size());
Department depart = departs.get(0);
System.out.println("直接左外连接查询结果集的第一个元素Department Name:" + depart.getName() + ",该department的Employees个数:" + depart.getEmployees().size()); departs = new ArrayList<>(new LinkedHashSet<>(departs));
System.out.println("使用LinkedHashSet排除重复项后集合个数:" + departs.size()); hql = "Select Distinct d FROM Department d INNER JOIN FETCH d.employees";
List<Department> departs2 = session.createQuery(hql).list();
System.out.println("使用Distinct排除重复项后集合个数:" + departs2.size());
for (Department department : departs2) {
System.out.println("使用Distinct排除重复项后元素Department Name:" + department.getName() + ",该department的Employees个数:" + department.getEmployees().size());
}
}

执行sql及结果:

 Hibernate:
select
department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
employees1_.ID as ID1_1_0__
from
DX_DEPARTMENT department0_
inner join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
直接左外连接查询结果集合个数:80
直接左外连接查询结果集的第一个元素Department Name:开发部门,该department的Employees个数:16
使用LinkedHashSet排除重复项后集合个数:5
Hibernate:
select
distinct department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
employees1_.ID as ID1_1_0__
from
DX_DEPARTMENT department0_
inner join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
使用Distinct排除重复项后集合个数:5
使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

内连接

1)INNER JOIN 关键字表示内连接,也可以省略INNER 关键字

2)list()方法的集合中存放的每个元素对应查询结果的一条记录,每个元素都是对象数组

3)如果希望list()方法的返回集合仅包含Department对象,可以在HQL查询语句中使用SELECT关键字。

测试函数:

     @Test
public void testInnerJoin() {
String hql = "FROM Department d INNER JOIN d.employees";
List<Department> departs = session.createQuery(hql).list(); System.out.println("直接左外连接查询结果集合个数:" + departs.size());
// 将会抛出异常:
// Department depart = departs.get(0);
// System.out.println("直接左外连接查询结果集的第一个元素Department Name:"
// +depart.getName() + ",该department的Employees个数:" +
// depart.getEmployees().size()); // 排重无效
departs = new ArrayList<>(new LinkedHashSet<>(departs));
System.out.println("使用LinkedHashSet排除重复项后集合个数:" + departs.size()); hql = "Select Distinct d FROM Department d INNER JOIN d.employees";
List<Department> departs2 = session.createQuery(hql).list();
System.out.println("使用Distinct排除重复项后集合个数:" + departs2.size());
for (Department department : departs2) {
System.out.println("使用Distinct排除重复项后元素Department Name:" + department.getName() + ",该department的Employees个数:" + department.getEmployees().size());
}
}

执行sql及结果:

 Hibernate:
select
department0_.ID as ID1_0_0_,
employees1_.ID as ID1_1_1_,
department0_.NAME as NAME2_0_0_,
employees1_.NAME as NAME2_1_1_,
employees1_.SALARY as SALARY3_1_1_,
employees1_.EMAIL as EMAIL4_1_1_,
employees1_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_DEPARTMENT department0_
inner join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
直接左外连接查询结果集合个数:80
使用LinkedHashSet排除重复项后集合个数:80
Hibernate:
select
distinct department0_.ID as ID1_0_,
department0_.NAME as NAME2_0_
from
DX_DEPARTMENT department0_
inner join
DX_EMPLOYEE employees1_
on department0_.ID=employees1_.DEPARTMENT_ID
使用Distinct排除重复项后集合个数:5
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
Hibernate:
select
employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
employees0_.ID as ID1_1_0_,
employees0_.ID as ID1_1_1_,
employees0_.NAME as NAME2_1_1_,
employees0_.SALARY as SALARY3_1_1_,
employees0_.EMAIL as EMAIL4_1_1_,
employees0_.DEPARTMENT_ID as DEPARTME5_1_1_
from
DX_EMPLOYEE employees0_
where
employees0_.DEPARTMENT_ID=?
使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

总结关联级别运行时的检索策略

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

2)HQL会忽略映射文件中设置的迫切左外连接检索策略,如果HQL采用迫切左外连接策略,就必须在HQL查询语句中显式的指定它

3)若在HQL代码中显式指定了检索策略,就会覆盖映射文件中配置的检索策略。

Hibernate(十四):HQL查询(三)的更多相关文章

  1. Hibernate中关于HQL查询返回List<Object>数据的结果集问题

    ---恢复内容开始--- 开发中遇到的一个小问题,使用Hibernate中的HQL查询时,使用query.list()查询出来的是一个List<Object>结果集 原来代码: publi ...

  2. Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加

    Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...

  3. Hibernate第四天——查询方式

    Hibernate入门最后一天第四天,我们进行查询方式的更进一步的细化: 先看一下大致的Hibernate的提供的查询的方式: 1.对象导航查询 2.OID查询 3.HQL查询 4.QBC查询 5.本 ...

  4. 【Hibernate步步为营】--hql查询小介

    HQL 是指Hibernate Query Language,它是Hibernate的查询语言,拥有一套自己的查询机制,它的查询语句和SQL非常类似.在使用的时候可以非常快上手.HQL提供了基本上SQ ...

  5. hibernate学习(7)——HQL查询

    1.HQL查询定义 Hibernate查询分类: 1. get/load 根据OID检索 2. 对象视图检索 c.getOrders 3. Sql语句 createSqlQuery 4. Hql语句 ...

  6. Hibernate框架之HQL查询与Criteria 查询的区别

    Hibernate框架提供了HQL查询和Criteria 查询.下面对这两种查询分别做个例子.也好对这两种查询方法有个大概的了解.就用房屋信息表做例子,查询所有房屋信息. HQL语句查询所有房屋信息: ...

  7. Hibernate用到HQL查询时的错误

    Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException: student is ...

  8. Hibernate(十二)Criteria查询

    一.简述 Criteria是一种比hql更面向对象的查询方式.Criteria 可使用 Criterion 和 Projection 设置查询条件.可以设置 FetchMode(联合查询抓取的模式 ) ...

  9. Java_Web三大框架之Hibernate+jsp+selvect+HQL查询数据

    俗话说:"好记性不如烂笔头".本人学习Hibernate也有一个星期了,对Hibernate也有一个初步的了解.下面对Hibernate显示数据做个笔记,使用租房系统的Hibern ...

  10. Hibernate学习之hql查询语句

    *  页面上数据的字段和数据库中字段差不多,这个时候,采用迫切连接  结构比较好,如果页面上的字段很少,要按照需求加载数据,采用带构造函数的select查询 实例讲解:转自:http://www.cn ...

随机推荐

  1. 用three.js创建一个简易的天空盒

    本文创建的天空盒是用六张图片来创建的.笔者会论述两种方法来创建,都是最简单基本的方法,不涉及着色器的使用.一种是创建一个盒子,然后将图片作为盒子6个面的纹理贴上来创建.另一种则是简单的将纹理作为场景的 ...

  2. 使用git将本地代码传到github

    方法可能有些小小的差别,但是最终的结果都是一样的 在github上新建代码仓库 确定之后会显示一个仓库的url,复制下来 在本地找一个作为本地仓库的文件夹右键Git Bash Here打开git 把g ...

  3. 笔记:Maven 生命周期与命令行详解

    Maven 拥有三套相互独立的生命周期,分别是 clean.default和site,clean 生命周期的目的是清理项目,default 生命周期的目的是构建项目,而site生命周期的目的是建立项目 ...

  4. protobuf(quickStart)

    1.简介 Protocol Buffers是Google开发一种数据描述语言,能够将数据进行序列化,可用于数据存储.通信协议等方面. 可以理解成更快.更简单.更小的JSON或者XML,区别在于Prot ...

  5. 用bat文件启动mongodb

    bat文件是dos下的批处理文件.批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用cm ...

  6. [css 揭秘]:CSS揭秘 技巧(二):多重边框

    我的github地址:https://github.com/FannieGirl/ifannie/ 源码都在这上面哦! 喜欢的给我一个星吧 多重边框 问题:我们通常希望在css代码层面以更灵活的方式来 ...

  7. node.js应用脚手架:koa2、sequelize、mysql

    自制了一个 nodejs 应用的脚手架. 基于 koa2 的,所以需要保证 node 环境至少为 7.6.0 吸取了以前的踩坑教训,添加了守护进程,确保应用不会因为异常导致网站直接挂掉(使用了 for ...

  8. Duplicate column name 'vocabulary'

    创建一个视图: 报错:Duplicate column name 'vocabulary' 意思是视图select的列名重复了,取别名 改成这样就ok了

  9. MySQL之集合函数与分组查询

    这是分组查询用到的语句,也包括了排序以及常用的集合函数

  10. 201621123050 《Java程序设计》第2周学习总结

    1.本周学习总结 java的数据类型 基本数据类型:介绍了java特有的boolean 引用数据类型 String:不变性:需要频繁修改时使用StringBuilder 包装类:自动拆.装箱 数组 一 ...