zoukankan      html  css  js  c++  java
  • Hibernate(十四):HQL查询(三)

    背景

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

    测试代码:

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

    执行sql及结果:

     1 Hibernate: 
     2     select
     3         department0_.ID as ID1_0_0_,
     4         employees1_.ID as ID1_1_1_,
     5         department0_.NAME as NAME2_0_0_,
     6         employees1_.NAME as NAME2_1_1_,
     7         employees1_.SALARY as SALARY3_1_1_,
     8         employees1_.EMAIL as EMAIL4_1_1_,
     9         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
    10         employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
    11         employees1_.ID as ID1_1_0__ 
    12     from
    13         DX_DEPARTMENT department0_ 
    14     left outer join
    15         DX_EMPLOYEE employees1_ 
    16             on department0_.ID=employees1_.DEPARTMENT_ID
    17 直接左外连接查询结果集合个数:80
    18 直接左外连接查询结果集的第一个元素Department Name:开发部门,该department的Employees个数:16
    19 使用LinkedHashSet排除重复项后集合个数:5
    20 Hibernate: 
    21     select
    22         distinct department0_.ID as ID1_0_0_,
    23         employees1_.ID as ID1_1_1_,
    24         department0_.NAME as NAME2_0_0_,
    25         employees1_.NAME as NAME2_1_1_,
    26         employees1_.SALARY as SALARY3_1_1_,
    27         employees1_.EMAIL as EMAIL4_1_1_,
    28         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
    29         employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
    30         employees1_.ID as ID1_1_0__ 
    31     from
    32         DX_DEPARTMENT department0_ 
    33     left outer join
    34         DX_EMPLOYEE employees1_ 
    35             on department0_.ID=employees1_.DEPARTMENT_ID
    36 使用Distinct排除重复项后集合个数:5
    37 使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
    38 使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
    39 使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
    40 使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
    41 使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

    左外连接

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

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

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

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

    测试代码:

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

    执行sql及结果

     1 Hibernate: 
     2     select
     3         department0_.ID as ID1_0_0_,
     4         employees1_.ID as ID1_1_1_,
     5         department0_.NAME as NAME2_0_0_,
     6         employees1_.NAME as NAME2_1_1_,
     7         employees1_.SALARY as SALARY3_1_1_,
     8         employees1_.EMAIL as EMAIL4_1_1_,
     9         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    10     from
    11         DX_DEPARTMENT department0_ 
    12     left outer join
    13         DX_EMPLOYEE employees1_ 
    14             on department0_.ID=employees1_.DEPARTMENT_ID
    15 直接左外连接查询结果集合个数:80
    16 使用LinkedHashSet排除重复项后集合个数:80
    17 Hibernate: 
    18     select
    19         distinct department0_.ID as ID1_0_,
    20         department0_.NAME as NAME2_0_ 
    21     from
    22         DX_DEPARTMENT department0_ 
    23     left outer join
    24         DX_EMPLOYEE employees1_ 
    25             on department0_.ID=employees1_.DEPARTMENT_ID
    26 使用Distinct排除重复项后集合个数:5
    27 Hibernate: 
    28     select
    29         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    30         employees0_.ID as ID1_1_0_,
    31         employees0_.ID as ID1_1_1_,
    32         employees0_.NAME as NAME2_1_1_,
    33         employees0_.SALARY as SALARY3_1_1_,
    34         employees0_.EMAIL as EMAIL4_1_1_,
    35         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    36     from
    37         DX_EMPLOYEE employees0_ 
    38     where
    39         employees0_.DEPARTMENT_ID=?
    40 使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
    41 Hibernate: 
    42     select
    43         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    44         employees0_.ID as ID1_1_0_,
    45         employees0_.ID as ID1_1_1_,
    46         employees0_.NAME as NAME2_1_1_,
    47         employees0_.SALARY as SALARY3_1_1_,
    48         employees0_.EMAIL as EMAIL4_1_1_,
    49         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    50     from
    51         DX_EMPLOYEE employees0_ 
    52     where
    53         employees0_.DEPARTMENT_ID=?
    54 使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
    55 Hibernate: 
    56     select
    57         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    58         employees0_.ID as ID1_1_0_,
    59         employees0_.ID as ID1_1_1_,
    60         employees0_.NAME as NAME2_1_1_,
    61         employees0_.SALARY as SALARY3_1_1_,
    62         employees0_.EMAIL as EMAIL4_1_1_,
    63         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    64     from
    65         DX_EMPLOYEE employees0_ 
    66     where
    67         employees0_.DEPARTMENT_ID=?
    68 使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
    69 Hibernate: 
    70     select
    71         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    72         employees0_.ID as ID1_1_0_,
    73         employees0_.ID as ID1_1_1_,
    74         employees0_.NAME as NAME2_1_1_,
    75         employees0_.SALARY as SALARY3_1_1_,
    76         employees0_.EMAIL as EMAIL4_1_1_,
    77         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    78     from
    79         DX_EMPLOYEE employees0_ 
    80     where
    81         employees0_.DEPARTMENT_ID=?
    82 使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
    83 Hibernate: 
    84     select
    85         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    86         employees0_.ID as ID1_1_0_,
    87         employees0_.ID as ID1_1_1_,
    88         employees0_.NAME as NAME2_1_1_,
    89         employees0_.SALARY as SALARY3_1_1_,
    90         employees0_.EMAIL as EMAIL4_1_1_,
    91         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    92     from
    93         DX_EMPLOYEE employees0_ 
    94     where
    95         employees0_.DEPARTMENT_ID=?
    96 使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

    HQL(迫切)内连接

     迫切内连接

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

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

    测试函数:

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

    执行sql及结果:

     1 Hibernate: 
     2     select
     3         department0_.ID as ID1_0_0_,
     4         employees1_.ID as ID1_1_1_,
     5         department0_.NAME as NAME2_0_0_,
     6         employees1_.NAME as NAME2_1_1_,
     7         employees1_.SALARY as SALARY3_1_1_,
     8         employees1_.EMAIL as EMAIL4_1_1_,
     9         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
    10         employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
    11         employees1_.ID as ID1_1_0__ 
    12     from
    13         DX_DEPARTMENT department0_ 
    14     inner join
    15         DX_EMPLOYEE employees1_ 
    16             on department0_.ID=employees1_.DEPARTMENT_ID
    17 直接左外连接查询结果集合个数:80
    18 直接左外连接查询结果集的第一个元素Department Name:开发部门,该department的Employees个数:16
    19 使用LinkedHashSet排除重复项后集合个数:5
    20 Hibernate: 
    21     select
    22         distinct department0_.ID as ID1_0_0_,
    23         employees1_.ID as ID1_1_1_,
    24         department0_.NAME as NAME2_0_0_,
    25         employees1_.NAME as NAME2_1_1_,
    26         employees1_.SALARY as SALARY3_1_1_,
    27         employees1_.EMAIL as EMAIL4_1_1_,
    28         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_,
    29         employees1_.DEPARTMENT_ID as DEPARTME5_1_0__,
    30         employees1_.ID as ID1_1_0__ 
    31     from
    32         DX_DEPARTMENT department0_ 
    33     inner join
    34         DX_EMPLOYEE employees1_ 
    35             on department0_.ID=employees1_.DEPARTMENT_ID
    36 使用Distinct排除重复项后集合个数:5
    37 使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
    38 使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
    39 使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
    40 使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
    41 使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

    内连接

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

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

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

    测试函数:

     1     @Test
     2     public void testInnerJoin() {
     3         String hql = "FROM Department d INNER JOIN d.employees";
     4         List<Department> departs = session.createQuery(hql).list();
     5 
     6         System.out.println("直接左外连接查询结果集合个数:" + departs.size());
     7         // 将会抛出异常:
     8         // Department depart = departs.get(0);
     9         // System.out.println("直接左外连接查询结果集的第一个元素Department Name:"
    10         // +depart.getName() + ",该department的Employees个数:" +
    11         // depart.getEmployees().size());
    12 
    13         // 排重无效
    14         departs = new ArrayList<>(new LinkedHashSet<>(departs));
    15         System.out.println("使用LinkedHashSet排除重复项后集合个数:" + departs.size());
    16 
    17         hql = "Select Distinct d FROM Department d INNER JOIN d.employees";
    18         List<Department> departs2 = session.createQuery(hql).list();
    19         System.out.println("使用Distinct排除重复项后集合个数:" + departs2.size());
    20         for (Department department : departs2) {
    21             System.out.println("使用Distinct排除重复项后元素Department Name:" + department.getName() + ",该department的Employees个数:" + department.getEmployees().size());
    22         }
    23     }

    执行sql及结果:

     1 Hibernate: 
     2     select
     3         department0_.ID as ID1_0_0_,
     4         employees1_.ID as ID1_1_1_,
     5         department0_.NAME as NAME2_0_0_,
     6         employees1_.NAME as NAME2_1_1_,
     7         employees1_.SALARY as SALARY3_1_1_,
     8         employees1_.EMAIL as EMAIL4_1_1_,
     9         employees1_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    10     from
    11         DX_DEPARTMENT department0_ 
    12     inner join
    13         DX_EMPLOYEE employees1_ 
    14             on department0_.ID=employees1_.DEPARTMENT_ID
    15 直接左外连接查询结果集合个数:80
    16 使用LinkedHashSet排除重复项后集合个数:80
    17 Hibernate: 
    18     select
    19         distinct department0_.ID as ID1_0_,
    20         department0_.NAME as NAME2_0_ 
    21     from
    22         DX_DEPARTMENT department0_ 
    23     inner join
    24         DX_EMPLOYEE employees1_ 
    25             on department0_.ID=employees1_.DEPARTMENT_ID
    26 使用Distinct排除重复项后集合个数:5
    27 Hibernate: 
    28     select
    29         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    30         employees0_.ID as ID1_1_0_,
    31         employees0_.ID as ID1_1_1_,
    32         employees0_.NAME as NAME2_1_1_,
    33         employees0_.SALARY as SALARY3_1_1_,
    34         employees0_.EMAIL as EMAIL4_1_1_,
    35         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    36     from
    37         DX_EMPLOYEE employees0_ 
    38     where
    39         employees0_.DEPARTMENT_ID=?
    40 使用Distinct排除重复项后元素Department Name:开发部门,该department的Employees个数:16
    41 Hibernate: 
    42     select
    43         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    44         employees0_.ID as ID1_1_0_,
    45         employees0_.ID as ID1_1_1_,
    46         employees0_.NAME as NAME2_1_1_,
    47         employees0_.SALARY as SALARY3_1_1_,
    48         employees0_.EMAIL as EMAIL4_1_1_,
    49         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    50     from
    51         DX_EMPLOYEE employees0_ 
    52     where
    53         employees0_.DEPARTMENT_ID=?
    54 使用Distinct排除重复项后元素Department Name:测试部门,该department的Employees个数:16
    55 Hibernate: 
    56     select
    57         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    58         employees0_.ID as ID1_1_0_,
    59         employees0_.ID as ID1_1_1_,
    60         employees0_.NAME as NAME2_1_1_,
    61         employees0_.SALARY as SALARY3_1_1_,
    62         employees0_.EMAIL as EMAIL4_1_1_,
    63         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    64     from
    65         DX_EMPLOYEE employees0_ 
    66     where
    67         employees0_.DEPARTMENT_ID=?
    68 使用Distinct排除重复项后元素Department Name:业务部门,该department的Employees个数:16
    69 Hibernate: 
    70     select
    71         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    72         employees0_.ID as ID1_1_0_,
    73         employees0_.ID as ID1_1_1_,
    74         employees0_.NAME as NAME2_1_1_,
    75         employees0_.SALARY as SALARY3_1_1_,
    76         employees0_.EMAIL as EMAIL4_1_1_,
    77         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    78     from
    79         DX_EMPLOYEE employees0_ 
    80     where
    81         employees0_.DEPARTMENT_ID=?
    82 使用Distinct排除重复项后元素Department Name:财务部门,该department的Employees个数:16
    83 Hibernate: 
    84     select
    85         employees0_.DEPARTMENT_ID as DEPARTME5_1_0_,
    86         employees0_.ID as ID1_1_0_,
    87         employees0_.ID as ID1_1_1_,
    88         employees0_.NAME as NAME2_1_1_,
    89         employees0_.SALARY as SALARY3_1_1_,
    90         employees0_.EMAIL as EMAIL4_1_1_,
    91         employees0_.DEPARTMENT_ID as DEPARTME5_1_1_ 
    92     from
    93         DX_EMPLOYEE employees0_ 
    94     where
    95         employees0_.DEPARTMENT_ID=?
    96 使用Distinct排除重复项后元素Department Name:行政部门,该department的Employees个数:16

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

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

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

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

  • 相关阅读:
    Ubuntu挂起后无法唤醒的问题以及解决方式
    两个比较给力的开源框架(1.头像选择,拍照,裁剪 2.自定义对话框)
    把APP演示做成GIF图
    单点触控与多点触控
    自定义imageView圆形图片
    自定义imageView圆形
    xmlBean类
    解析xml并展示数据(fragment)
    解析xml并展示数据(mainActivity)
    XStream解析xml代码
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/6984925.html
Copyright © 2011-2022 走看看