Hibernate学习总结(7)

9.Hibernate加载计划和策略

9.1Hibernate提供了下列方法从数据库中获取对象:
1、通过get()或load()方法按照id获取对象。
2、从一个已经加载的对象开始,通过系列的get方法访问被关联的对象。
3、HQL查询获取单个或系列对象。
4、Criteria查询获取单个或系列对象。
5、原生SQL查询获取单个或系列对象。

9.2加载计划

我们要关注的是主对象及其关联对象的加载计划和加载策略,即数据何时被加载以及数据被怎样加载的问题。
(1)涉及到加载计划(何时加载)的关注点有以下几个:
1、主对象的关联对象何时被加载
2、主对象的关联集合何时被加载
3、主对象本身何时被加载
4、主对象的属性何时被加载

(2)默认加载计划

1、关联对象和关联集合的默认加载计划是:延迟加载,即加载主对象时它们不会被立即加载,而是直到使用这些对象和集合时才发送SQL语句、获取数据、初始化对象和集合。
2、主对象本身是否延迟加载取决于使用的是load()方法还是其它方法,load()方法是延迟的,而get()方法或其它方法是立即的。
3、主对象的属性默认是被立即加载的。

(3)改变默认加载计划

可以通过修改对应类的实体映射文件,改变默认的加载计划。

但不建议这样做,因为这样配置之后,不管是否需要关联数据,Hibernate都会加载,这样会造成大量的内存浪费。最好是采用编程方式在特定情况下进行立即加载(也称热加载),比如我们之前提到的HQL fetch join或者在Criteria查询中设置FetchMode。
(4)get()与load()的对比

load()是延迟加载的。

get和load方式是根据id取得一个记录;
1.从返回结果上对比: load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 get方法检索不到的话会返回null
2.从检索执行机制上对比: get方法和find方法都是直接从数据库中检索 而load方法的执行则比较复杂首先查找session的persistent Context中是否有缓存,如果有则直接返回 如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null 在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果 找不到就抛出异常。

参考:http://www.cnblogs.com/binjoo/articles/1621254.html

(6)属性的加载计划

需要注意的是,普通属性的默认加载计划是立即加载,这一点我们也可以改变。

Hibernate3开始增加了property节点的lazy属性,为特定的属性指定延迟加载计划,以避免主对象整体加载可能带来的性能浪费,尤其是针对大数据量的属性。

 

10.Hibernate高速缓存

10.1Hibernate一级缓存

Hibernate一级缓存的生命周期跟Session的生命周期一样,所以也可以将Hibernate一级缓存称为Session缓存。Hibernate一级缓存是一个强制的高速缓存。

它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,一般情况下无需进行干预。

(1)get()方法会去一级缓存中查找获取数据(又称命中数据),并且将查询结果放置在一级缓存中。load()也一样。

(2)list()方法会将查询结果放置在一级缓存中,但是它不会去一级缓存中查找获取数据,原因是list()方法不是通过id加载的。
(3)iterate方法

Iterator<Seeker> iter = session.createQuery(“from **").iterate(); 

该语句只把ID的值放到迭代器中,当遍历的时候,会根据ID的值再去数据库中查。并且该语句会产生N+1次查询。

iterate查询针对实体(不是针对属性查询)的时候会采用N+1的方式,加载实体对象前会做一级缓存命中(如果iterate之前已经做过查询,iterate作缓存命中,就不需要有N+1查询),并且将实体缓存起来。

(4)session.clear()方法一次性清除一级缓存中的所有数据。

(5)session.evict(Object object)方法是清楚一级缓存中指定对象。
(6)flush()和clear()

在数据量比较大的情况下,管理一级缓存的做法一般都是在一定数量的更新或者保存等操作之后,使用flush()和clear()方法将数据同步到数据库并清除一级缓存,从而避免一次性大量实体数据的缓存导致内存溢出。

Session session = getSession();
session.beginTransaction();
for(int i=0;i<10000;i++){  
Seeker s = new Seeker();  
s.setName("s" + i);  
session.save(s); //save()、update()方法后的持久态对象会被缓存
if(i%20 == 0) {
	session.flush();  
	session.clear();  
}  
} 
session.getTransaction().commit();
session.close();

10.2Hibernate二级缓存

二级缓存是一个可选的缓存插件,它由SessionFactory负责管理,所以也常将二级缓存称为SessionFactory缓存。
由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此二级缓存是进程范围的缓存,可以被线程共享,所以可能存在并发问题,因此需要采用适当的并发访问策略。
二级缓存对实体类是可选的,可以在每个类或每个集合的粒度上配置二级缓存。Hibernate的二级缓存策略,是针对于id查询的缓存策略,对于条件查询则毫无作用。

(1)适用于:

1、 很少被修改的数据;
2、 不是很重要的数据;
3、 不会被并发访问的数据。

(2)不适用于:

1、 经常被修改的数据;
2、 财务数据;
3、 与其他应用共享的数据。
(3) 常用的缓存插件

Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
l EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
l OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
l SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
l JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值