背景

基于上两章节《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. vuex入门

    安装&使用 npm install vuex --save 1 通过Vue.use()来使用: import Vue from 'vue' import Vuex from 'vuex' Vu ...

  2. DOM生成XML文档

    import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuil ...

  3. 前端的UI设计与交互之布局篇

    布局是页面构成的前提,是后续展开交互和视觉设计的基础.设计者在选择布局之前,需要注意以下几点原则:明确用户在此场景中完成的主要任务和需获取的决策信息.明确决策信息和操作的优先级及内容特点,选择合理布局 ...

  4. 搭建nuxtjs程序 —— 用户信息 or token怎么不丢失

    框架背景:开发框架采用vue,需要更好的SEO,更快的内容到达时间,从浏览器看不到对服务器的请求接口,选用开箱即用的nuxtjs. 问题背景:1. 前后分离,需前端存储token及登录后的用户信息: ...

  5. linux-2.6.18源码分析笔记---信号

    一.相关数据结构及其位置(大致浏览即可,介绍流程时再来仔细看) 1.1 进程描述符struct task_struct所在目录:include\linux\sched.h 关注task_struct中 ...

  6. java中equals相同,hashcode一定相同ma

    一.jdk中equals和hashcode的定义和源码进行分析 1.java.lang.Object中对equals()方法的定义 java.lang.Object中对hashCode()方法的定义 ...

  7. Sweet Butter 香甜的黄油

    Sweet Butter 香甜的黄油 题目大意:m个点,n头奶牛,p条边,每一头奶牛在一个点上,一个点可以有多只奶牛,求这样一个点,使得所有奶牛到这个点的距离之和最小. 注释:n<=500 , ...

  8. ansible之一:安装与配置

    ansible特点: 1.不需要安装客户端,通过sshd去通信 2.基于模块工作,模块可以由任何语言开发 3.不仅支持命令行试用模块,也支持yaml格式得playbook 4.支持sudo 5.有提供 ...

  9. 爬虫(scrapy--豆瓣TOP250)

    # -*- coding: utf-8 -*- import scrapy from douban_top250.items import DoubanTop250Item class MovieSp ...

  10. java设计模式-State(状态)模式

    state定义     不同的状态,不同的行为;或者说,每个状态有着相应的行为.         就像电风扇的开关,一档的上一个是关闭,关闭的上一个是五档,五档的上一个是四档,以此类推,而且五档的下一 ...