Hibernate(十四):HQL查询(三)
背景
基于上两章节《Hibernate(十二):HQL查询(一)》、《Hibernate(十三):HQL查询(二)》,已经学习了一部分关于HQL的用法:
- HQL带参数查询
- HQL Order By排序查询
- HQL 设置实体参数查询
- HQL分页查询
- HQL命名语句查询
- HQL投影查询
- 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查询(三)的更多相关文章
- Hibernate中关于HQL查询返回List<Object>数据的结果集问题
---恢复内容开始--- 开发中遇到的一个小问题,使用Hibernate中的HQL查询时,使用query.list()查询出来的是一个List<Object>结果集 原来代码: publi ...
- Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加
Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...
- Hibernate第四天——查询方式
Hibernate入门最后一天第四天,我们进行查询方式的更进一步的细化: 先看一下大致的Hibernate的提供的查询的方式: 1.对象导航查询 2.OID查询 3.HQL查询 4.QBC查询 5.本 ...
- 【Hibernate步步为营】--hql查询小介
HQL 是指Hibernate Query Language,它是Hibernate的查询语言,拥有一套自己的查询机制,它的查询语句和SQL非常类似.在使用的时候可以非常快上手.HQL提供了基本上SQ ...
- hibernate学习(7)——HQL查询
1.HQL查询定义 Hibernate查询分类: 1. get/load 根据OID检索 2. 对象视图检索 c.getOrders 3. Sql语句 createSqlQuery 4. Hql语句 ...
- Hibernate框架之HQL查询与Criteria 查询的区别
Hibernate框架提供了HQL查询和Criteria 查询.下面对这两种查询分别做个例子.也好对这两种查询方法有个大概的了解.就用房屋信息表做例子,查询所有房屋信息. HQL语句查询所有房屋信息: ...
- Hibernate用到HQL查询时的错误
Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException: student is ...
- Hibernate(十二)Criteria查询
一.简述 Criteria是一种比hql更面向对象的查询方式.Criteria 可使用 Criterion 和 Projection 设置查询条件.可以设置 FetchMode(联合查询抓取的模式 ) ...
- Java_Web三大框架之Hibernate+jsp+selvect+HQL查询数据
俗话说:"好记性不如烂笔头".本人学习Hibernate也有一个星期了,对Hibernate也有一个初步的了解.下面对Hibernate显示数据做个笔记,使用租房系统的Hibern ...
- Hibernate学习之hql查询语句
* 页面上数据的字段和数据库中字段差不多,这个时候,采用迫切连接 结构比较好,如果页面上的字段很少,要按照需求加载数据,采用带构造函数的select查询 实例讲解:转自:http://www.cn ...
随机推荐
- vuex入门
安装&使用 npm install vuex --save 1 通过Vue.use()来使用: import Vue from 'vue' import Vuex from 'vuex' Vu ...
- DOM生成XML文档
import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuil ...
- 前端的UI设计与交互之布局篇
布局是页面构成的前提,是后续展开交互和视觉设计的基础.设计者在选择布局之前,需要注意以下几点原则:明确用户在此场景中完成的主要任务和需获取的决策信息.明确决策信息和操作的优先级及内容特点,选择合理布局 ...
- 搭建nuxtjs程序 —— 用户信息 or token怎么不丢失
框架背景:开发框架采用vue,需要更好的SEO,更快的内容到达时间,从浏览器看不到对服务器的请求接口,选用开箱即用的nuxtjs. 问题背景:1. 前后分离,需前端存储token及登录后的用户信息: ...
- linux-2.6.18源码分析笔记---信号
一.相关数据结构及其位置(大致浏览即可,介绍流程时再来仔细看) 1.1 进程描述符struct task_struct所在目录:include\linux\sched.h 关注task_struct中 ...
- java中equals相同,hashcode一定相同ma
一.jdk中equals和hashcode的定义和源码进行分析 1.java.lang.Object中对equals()方法的定义 java.lang.Object中对hashCode()方法的定义 ...
- Sweet Butter 香甜的黄油
Sweet Butter 香甜的黄油 题目大意:m个点,n头奶牛,p条边,每一头奶牛在一个点上,一个点可以有多只奶牛,求这样一个点,使得所有奶牛到这个点的距离之和最小. 注释:n<=500 , ...
- ansible之一:安装与配置
ansible特点: 1.不需要安装客户端,通过sshd去通信 2.基于模块工作,模块可以由任何语言开发 3.不仅支持命令行试用模块,也支持yaml格式得playbook 4.支持sudo 5.有提供 ...
- 爬虫(scrapy--豆瓣TOP250)
# -*- coding: utf-8 -*- import scrapy from douban_top250.items import DoubanTop250Item class MovieSp ...
- java设计模式-State(状态)模式
state定义 不同的状态,不同的行为;或者说,每个状态有着相应的行为. 就像电风扇的开关,一档的上一个是关闭,关闭的上一个是五档,五档的上一个是四档,以此类推,而且五档的下一 ...