背景

基于上两章节《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. 设计模式之生成器(Builder)模式

    意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以表示不同的表示. 适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 当构造过程必须允许被构造的对象有不同的表 ...

  2. 笔记:Spring Cloud Hystrix 服务容错保护

    由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加 ...

  3. POJ1331 Multiply(strtol函数练习)

    题目链接:http://poj.org/problem?id=1331 主要介绍strtol函数: long int strtol(const char *nptr,char **endptr,int ...

  4. 利用CSS3制作网页动画

    如何在网页中实现动画效果动态图片 flashjavascriptcss3变形是一些效果的集合如平移 旋转 缩放 倾斜效果每个效果都可以称为变形(transfrom) 它们可以分别操控元素发生平移.旋转 ...

  5. 推荐一个利用 python 生成 pptx 分析报告的工具包:reportgen

    reportgen v0.1.8 更新介绍 这段时间,我对 reportgen 进行了大工程量的修改和更新.将之前在各个文章中出现的函数进行了封装,同时也对现有工具包的一些逻辑进行了调整. 1.rep ...

  6. sqlserver 简单的创建数据库

    简简单单,作为不是牛逼的程序来说,这是很容易忘记的sql语句: use mastergo --判断是否存在该数据库if exists(select *from Sysdatabases where n ...

  7. 用python程序来画花

    from turtle import * import time setup(600,800,0,0) speed(0) penup() seth(90) fd(340) seth(0) pendow ...

  8. JDK1.8源码(六)——java.util.LinkedList 类

    上一篇博客我们介绍了List集合的一种典型实现 ArrayList,我们知道 ArrayList 是由数组构成的,本篇博客我们介绍 List 集合的另一种典型实现 LinkedList,这是一个有链表 ...

  9. C语言第二周作业

    一.PTA实验作业 题目一:7-1 计算分段函数 1.实验代码 double x,y; scanf("%lf", &x); if(x >= 0){ y=pow(x,0 ...

  10. 20162330 实验四 《Android程序设计》 实验报告

    2016-2017-2 实验报告目录: 1 2 3 4 5 20162330 实验四 <Android程序设计> 实验报告 课程名称:<程序设计与数据结构> 学生班级:1623 ...