Hibernate(十四):HQL查询(三)
2017-06-11 13:09
288 查看
背景
基于上两章节《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根据条件动态组装sql/hql语句(仿ibatis动态查询语句功能)
- 【Hibernate步步为营】--hql查询之实体对象查询
- JSP 开发之hibernate的hql查询多对多查询
- Hibernate的HQL查询及原生sql查询语句写法
- Hibernate查询语言HQL
- Hibernate 查询语句HQL基本语法
- HQL子查询报错:org.hibernate.hql.ast.QuerySyntaxException: unexpected token...
- Hibernate中HQL对查询结果进行排序2015-11-14
- HQL: Hibernate查询语言
- 【hibernate】——hql简单属性+实体对象查询
- Hibernate查询结果转换为实体类型 (HQL/SQL)
- 精通Hibernate——HQL查询详解
- hibernate的hql模糊查询例子
- Hibernate查询(HQL)
- Hibernate(一)HQL查询、原生sql查询
- Hibernate查询数据的几种方式以及HQL用法及参数的几种使用方法
- Hibernate查询语言:HQL
- hibernate——HQL查询(一)
- Hibernate中使用HQL进行分页查询