1.1概念
即在建立关联关系的情况下,在加载当时对象时对象时,对关联对象的检索策略。合理设置关联关系,可以提高软件的效率。
1.2立即检索策略
实现方法:将<set>元素的lazy设置为false
检索方式:立即初始化与当前对相关联的对象
优点:即使当前状态为游离状态,也可以方便地从当前对象导航到与之关联的对象
缺点:执行太多的select语句,增加访问数据库的次数,还可能加载程序中不需要的对象,既浪费时间又浪费缓存空间
优先考虑使用的场合:
(1) 在程序中需要立即访问关联对象
(2) 使用二级缓存
注意事项:
(1)在一对多关联中应该尽量避免立即检索,特殊情况除外
(2)在多对一关联中应根据实际情况决定采用何种检索策略
1.3一对多的立即检索
Hibernate默认情况下,一对多关联采用用户演示检索策略。因为通常情况下,在程序中不需在立即访问关联对象,如果这种情况下采用立即检索,无疑会执行多余的select语句,加长了加载时间,占用了缓存空间。如果在特殊情况下可以设置为一对多的立即检索。
//一对多的检索测试
@Test
public void fun3(){
Session currentSession = HibernateUtil.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
List<Employee> list = currentSession.createQuery("from Employee").list();
for (int i = 0; i <list.size() ; i++) {
System.out.println(list);
}
transaction.commit();
HibernateUtil.close(currentSession);
}
1.4延时缓存
实现方法:将<set>元素的lazy设置为true,lazy的默认值为true
检索方式:不立即初始化与当前的对相关联的对象。而是为关联对象创建一个代理对象,该对象只有OID被初始化,只有该代理对象的其他属性被请求时,对初始化该代理对象。
优点:由程序动态控制对象的加载,可以避免执行不必要的select语句加载不需要的对象,可以节省时间和缓存
缺点:当访问处于游离状态的对象时,必须保证关键对象已经被初始化。
优先考虑使用场景:
(1)一对多或多对多关联
(2)在程序不需要立即访问与之关联的对象
1.5类级别检索
get:立即检索。get方法一执行,立即查询所有字段的数据。
load:延迟检索。默认情况,load方法执行后,如果只使用OID的值不进行查询,如果要使用其他属性值将查询 。 Customer.hbm.xml <class lazy="true |false">
lazy默认值true,表示延迟检索,如果设置false表示立即检索。
1. get/load
get: 立即查询数据库,将数据初始化
load: hbm文件中,class元素的lazy属性决定类级别load方法的加载策略
true:先返回一个代理对象.使用代理对象的属性时,才去查询数据库.
false: 与get一致,会立即加载数据
一对多或多对多
容器<set> 提供两个属性:fetch、lazy
fetch:确定使用sql格式
lazy:关联对象是否延迟。
fetch:join、select、subselect
join:底层使用迫切左外连接
select:使用多个select语句(默认值)
subselect:使用子查询
lazy:false、true、extra
false:立即
true:延迟(默认值)
extra:极其懒惰
fetch="select"
当前对象 和 关联对象 使用多条select语句查询。
lazy="false" , 立即,先查询客户select,立即查询订单select
lazy="true",延迟,先查询客户select,需要订单时,再查询订单select
lazy="extra",极其懒惰(延迟),先查询客户select, 如果只需要订单数,使用聚合函数(不查询详情)
关联级别加载策略
在查询有关联关系的数据时,加载一方的数据是否需要将另一方立即查询出.
默认: 与我关联的数据,在使用时才会加载.
集合(一对多):
set
lazy: 是否对set数据使用懒加载
true:(默认值) 对集合使用才加载
false: 集合将会被立即加载
extra: 极其懒惰,如果使用集合时,之调用size方法查询数量, Hibernate会发送count语句,只查询数量.不加载集合内数据.
fetch : 决定加载集合使用的sql语句种类
select: (默认值) 普通select查询
join: 表链接语句查询集合数据
subselect: 使用子查询 一次加载多个Customer的订单数据
1.6批量检索策略
在映入一对多关联中,还可以通过Hibernate提供的批量检索功能,实现批量检索数据,减少执行select语句的条数,从而减少访问数据库的次数,提升软件的性能。
批量检索功能的实现要和立即检索或延时间所联合使用。通过配置<set>元素的batch-size属性实现,在默认情况下值为1,经过大量的实践证明:batch-size的合理取值应该在2到10之间,如果值过大,复杂的sql语句会影响加载的速度,如果采用延时加载。会降低延时检索的意义。
在默认情况下,初始化每个当前对象都要执行一条select语句,如果设置为2,执行一条select语句则可以初始化包含当前对象在内的两个对象的所有关联对象。
1.7迫切左外连接检索策略
迫切左外连接检索策略与立即检所实现的功能相同,区别在于前者只需要执行一条select语句,而后者需执行多条select语句,相对而言减少了访问数据库的次数,不过单次访问时间上有所增加,以为select语句的复杂度增加了。
实现方法:将<set>元素的fetch设置为join
String hql2="from Employee e left join fetch e.enterprise";
检索方式:立即初始化与当前对相关联的对象,该检索只对session的load()和get()方法有效。当同时使用延时检索和迫切左外连接检索时,后者将覆盖前者。
优点:无论当前对象处于持久还是游离状态,都可以关联到与之关联的对象,并且比立即检索策略执行的sql语句少,只执行一条sql语句。
缺点:可能加载当前对象不需要的对象,增加缓存的使用率,复杂的select语句会影响检索功能
使用场景:
(1)一对一或多对一关联
(2)在程序中需要立即访问与之关联的对象
(3)具有良好的数据库表结构
实现迫切左外连接检索有两种方式:
(1)通过配置文件实现
(2)通过HQL语句实现
1.8通过配置文件实现
在配置文件中配置迫切左外连接检索只对session的get()和load()方法有效。迫切左外连接检索策略配置映射文件的fetch属性来实现,在<many-to-one><one-to-many>和<set>元素中拥有该属性。