Hibernate连接查询和注解
前言
实现HQL的连接查询和注解进行关联数据库字段
HQL的连接查询
和SQL查询一样,HQL也支持多种连接查询,如内连接、外连接。还允许显示指定迫切内连接和迫切左外连接。迫切连接指不仅指定了连接查询方式,而且显式地指定了关联级别的查询策略。迫切连接使用fetch关键字实现,fetch关键字表明”左边“对象用来与”右边“对象关联的属性会立即被初始化。
HQL支持的常用连接类型
- 内连接 - inner join 或 join
from Entity [inner] join [fetch] Entity.property
- 切内连接 - inner join fetch 或 join fetch
- 左外连接 - left outer join 或 join
- 迫切左外连接 - left outer join fetch 或 left join fetch
- 右外连接 - 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子句中,子查询语句需要放在()里面。
子查询关键字
- all - 子查询语句返回的所有记录
- any - 子查询语句返回的任意一条记录
- some - 与any意思相同
- in - 与 =any意思相同
- exists - 子查询语句至少返回一条记录
操作集合的函数或属性
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程序的文件数量大大精简。
使用注解配置持久化类及对象关联关系
在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类
<mapping class="持久化类完整限定名"/>
配置持久化类的常用注解
- @Entity - 将一个类声明为一个持久化类
- @Table - 为持久化类映射指定表(table)、目录(catalog)、schema名称
- @Id - 声明持久化类的标识属性(主键)
- @GeneratedValue - 定义表示属性值的生成策略
- @UniqueConstraint - 定义表的唯一约束
- @Lob - 表示属性将被持久化为Blob或者Clob类型
- @Column - 将属性映射到数据字段
- @Transient - 指定可以忽略的属性,不用持久化到数据库
使用Hibernate注解需要导入javax.persistence包。
使用注解配置关联关系
- @OneToOne - 建立持久化类之间的一对一关联关系
- @OneToMany - 建立持久化类之间的一对多关联关系
- @ManyToOne - 建立持久化类之间的多对一关联关系
- @ManyToMany - 建立持久化类之间的多对多关联关系
- @JoinColumn - 建立连接后关系指明自己在对方类型中的属性名
- @JoinColumns - 建立多对多关系指明自己的字段和关联字段