Hibernate连接查询和注解

       前言

        实现HQL的连接查询和注解进行关联数据库字段


HQL的连接查询

        和SQL查询一样,HQL也支持多种连接查询,如内连接、外连接。还允许显示指定迫切内连接和迫切左外连接。迫切连接指不仅指定了连接查询方式,而且显式地指定了关联级别的查询策略。迫切连接使用fetch关键字实现,fetch关键字表明”左边“对象用来与”右边“对象关联的属性会立即被初始化。

HQL支持的常用连接类型

  1. 内连接 - inner join 或 join
    from Entity [inner] join [fetch] Entity.property
  2. 切内连接 - inner join fetch 或 join fetch
  3. 左外连接 - left outer join 或 join
  4. 迫切左外连接 - left outer join fetch 或 left join fetch
  5. 右外连接 - right outer join 或 right join
    from Entity [left|right] [outer] join [fetch] Entity.property
  • 等值连接

        HQL支持SQL风格的等值连接查询。等值连接适用于两个类之间没有定义任何关联时。

from Entity1 e1,Entity2 e2 [inner] join [fetch] e1 = e2.property
  • 隐式内连接

        在HQL查询语句中,对Emp类可以通过e.dept.deptName的形式访问其关联的dept对象的deptName属性。

        fetch关键字只对inner join和left outer join有效。对于right outer join而言,由于作为关联对象容器的“左边”对象可能为null,所以无法通过fetch关键字强制Hibernate进集合填充操作。


分组统计数据

        HQL和SQL一样,使用group by关键字对数据分组,使用having关键字对分组数据设定约束条件,从而完成对数据分组和统计。

[select ... ]from ...[where...][group by...[having...]][order by...]
  • 聚合函数
    • count() - 统计记录数
    • sum() - 求和
    • min() - 求最小值
    • max() - 求最大值
    • avg() - 求平均值
Long count - (Long)session.createQuery("select count(id) from Dept").uniqueResult();

Object [] salarys = (Object[])session.createQuery("select max(salary),min(salary),avg(salary) from Emp").uniqueResult();

        因为聚合函数全部都是只取一行,所以使用uniqueResult()方法获取。如果一行有选取多个对象时,uniqueResult()返回一个Object数组。

  • 分组查询

        HQL查询语句使用group by子句进行分组查询,使用having子句筛选分组结果。

List<Object[]> list = HibernateUtil.currentSession().createQuery("select job,count(e) from Emp group by job").list();

        Query的list()方法返回的集合中包含Object[]类型的元素,每个Object[]对应查询结果中的一条记录,数据的第一个元素是职位名称,第二个元素是该职位的员工人数。having子句用于筛选分组结果。


子查询

        子查询应用的HQL语句的where子句中,子查询语句需要放在()里面。

  1. 子查询关键字

    • all - 子查询语句返回的所有记录
    • any - 子查询语句返回的任意一条记录
    • some - 与any意思相同
    • in - 与 =any意思相同
    • exists - 子查询语句至少返回一条记录
  2. 操作集合的函数或属性

    HQL提供了操作集合的函数或属性

    • size()或size - 获取集合中元素的数目
    • minIndex()或minIndex - 对于建立了索引的集合,获得最小的索引
    • maxIndex()或maxIndex - 对于建立了索引的集合,获得最大的索引
    • minElement()或minElement - 对于包含基本类型元素的集合,获得集合中取值最小的元素
    • maxElement()或maxElement - 对于包含基本类型元素的集合,获得集合中取值最大的元素
    • elements() - 获取集合中所有元素

查询性能优化
  • Hibernate查询优化策略

    • 使用迫切左外连接或迫切内连接查询策略、配置二级缓存和查询缓存等方式,减少select语句的数目,降低访问数据库的频率。
    • 使用延迟加载等方式避免加载多余的不需要访问的数据
    • 使用Query接口的iterate()方法减少select语句中的字段,降低访问数据库的数据量。结合缓存等机制减少数据库访问次数,提高查询效率。
    • Query接口的list()和iterate()都可以执行查询,而iterate()方法能够利用延迟加载和缓存机制提高查询性能。iterate()方法执行时仅查询ID字段以节省资源,需要使用数据时在根据ID字段到缓存中检索匹配的实例,如果存在就直接使用,只有当缓存中没有需要的数据时,iterate()方法才会执行select语句根据ID字段到数据库中查询。iterate()方法更适用于查询对象开启二级缓存的情况。
  • HQL优化

    • 避免使用not。如果where子句的条件包含not关键字,那么执行该字段的索引失效。这些语句需要分成不同情况区别对待,如果查询租金不多于1800的租房信息HQL语句为

      from House as h where not (h.price>1800)
    • 避免like的特殊形式。某些情况下,会在where子句条件中使用like。如果like以一个%或)开始即前模糊,则该字段的索引不起作用。

    • 避免having子句。在分组的查询语句中,可在两个位置指定条件,一是在where子句中,而是在having子句中。要尽可能的在where子句中而不是having子句中指定条件。having是在检索出所有记录后才对结果集进行过滤,这个处理需要一定的开销,而where子句限制记录数据,能减少这方面的开销。

    • 避免使用distinct。指定distinct会导致在结果中删除重复的行,这会对处理时间造成一定的影响。

    • 对字段使用函数,该字段的索引将不起作用。

    • 对字段进行计算,该字段的索引将不起作用。

        HQL优化是Hibernate程序优化的一个方面,HQL语法与SQL非常类似。HQL是基于SQL的,只有增加了面向对象的封装。如果抛开HQL同Hibernate本身一些缓存机制的关联,HQL的优化技巧同SQL的优化技巧一样。


注解

        Hibernate提供了注解来进行对象关系映射,它可以代替大量的hbm.xml文件,使Hibernate程序的文件数量大大精简。

  1. 使用注解配置持久化类及对象关联关系

  2. 在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类

    <mapping class="持久化类完整限定名"/>
  3. 配置持久化类的常用注解

    • @Entity - 将一个类声明为一个持久化类
    • @Table - 为持久化类映射指定表(table)、目录(catalog)、schema名称
    • @Id - 声明持久化类的标识属性(主键)
    • @GeneratedValue - 定义表示属性值的生成策略
    • @UniqueConstraint - 定义表的唯一约束
    • @Lob - 表示属性将被持久化为Blob或者Clob类型
    • @Column - 将属性映射到数据字段
    • @Transient - 指定可以忽略的属性,不用持久化到数据库

使用Hibernate注解需要导入javax.persistence包。

使用注解配置关联关系

  • @OneToOne - 建立持久化类之间的一对一关联关系
  • @OneToMany - 建立持久化类之间的一对多关联关系
  • @ManyToOne - 建立持久化类之间的多对一关联关系
  • @ManyToMany - 建立持久化类之间的多对多关联关系
  • @JoinColumn - 建立连接后关系指明自己在对方类型中的属性名
  • @JoinColumns - 建立多对多关系指明自己的字段和关联字段