Hibernate学习笔记之缓存

一、持久化缓存的范围

缓存的范围决定了缓存的生命周期以及可以被谁访问。
事务级缓存:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。每个事务都有独自的缓存。
应用级缓存:缓存被应用内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期。
分布式缓存:在分布式环境中,缓存被一个机器或者多个机器的应用共享。缓存中的数据被复制到分布式环境中的每个应用节点,应用通过远程通信来保证缓存中的数据的一致性。对大多数应用来说,应该慎重地考虑是否需要使用分布式范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。

 

二、Hibernate数据缓存(Cache)分为两个层次:
1、Session Level缓存
Session的缓存是内置的,不能被卸载,也被称为Hibernate的一级缓存。
2、SessionFactory Level 缓存
SessionFactory的缓存是应用级缓存,包含二个部分:内置缓存和外置缓存。SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句。SessionFactory的外置缓存是一个可配置的插件,通常说的Hibernate二级缓存就是SessionFactory外置缓存,在默认情况下,Hibernate并没有打开二级缓存。

 

三、Hibernate中,缓存在以下情况下发挥作用:
1、通过id(主键)加载数据时
包括根据id查询数据的Session.load/get方法,以及Query/Criteria的iterate方法 。
2、延迟加载
通过延迟加载读取的数据对象可以通过id从缓存读取。

 

四、一级缓存
Hibernate的Session内部缓存也称为一级缓存,属于事务级缓存。Session在内部维护了一个Map数据类型,其中保持了所有与当前Session相关联的数据对象。

若需要通过Sessoin加载某个数据对象,Session首先会根据所要加载的数据类型和id,在一级缓存中寻找是否已有些数据的缓存实例,如果存在且状态有效,则以此数据实例作为返回结果。
当Session从数据库加载数据时,也会将其以对象的形式存放到一级缓存中加以管理的。
一级缓存是Session的私有数据,伴随Session实例的创建而创建,消亡而消亡。一级缓存不能在Session间共享。
一级缓存正常情况下是由Hibernate自动维护的,但也可通过Session.evict方法、Session.clear方法进行干预,evict方法将某个特定对象从一级缓存中清除。clear方法则清空整个一级缓存。

 

五、二级缓存
在Hibernate中的二级缓存可以是应用级缓存,也可是分布式缓存。
二级缓存是SessionFactory级别的全局缓存。Session在进行数据查询时,如在自身的一级缓存中查询未果,则将在二级缓存中查找,若命中,则以命中的数据对象作为结果返回。

 

六、二级缓存策略
缓存策略决定了数据对象在缓存中的存取规则。
要使用Hibernate的二级缓存,需为每个实体类指定相应的缓存策略。
Hibernate提供了四种内置的缓存策略:
read-only:只读,如果修改会抛出异常。对于从来不会修改的数据,如参考数据,可以使用只读型缓存。
nonstrict-read-write:不严格的读/写缓存。不保证缓存与数据库中数据的一致性。若程序对并发访问下的数据同步要求不是很严格,且数据更新操作频率较低,可采用此策略缓存。性能比读写缓存好。
read-write:严格读写缓存。用于对数据同步要求严格的情况,对于经常被读、较少修改的数据,可以采用此策略缓存。不支持分布式缓存。实际应用最广泛的缓存策略。
读写缓存和不严格读写缓存在实现上的区别在于,读写缓存更新缓存的时候会把缓存里面的数据换成一个锁,其他事务如果去取相应的缓存数据,发现被锁住了,就直接查询取数据库。如果锁住部分缓存的事务发生了异常,那么缓存会一直被锁住,直到超时。不严格读写缓存不锁定缓存中的数据。

transactional:事务型缓存。缓存支持事务,发生异常的时候,缓存也能够回滚。必须运行在JTA事务环境中。适用于对关键数据的缓存。

 

ps:使用Annotation @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)写了一个小例子,但是修改缓存中的数据对象后其他对象并没有去数据库取,而是取到了修改后的对象,在此标注一下后续研究。

 

Hibernate生成sql语句:

Hibernate: select tuser0_.id as id0_0_, tuser0_.name as name0_0_ from cui_user tuser0_ where tuser0_.id=?
1---test         //将对象加载到缓存
2---cuisea     //从缓存中读取数据,并修改name
3---cuisea    //奇怪这里也是从缓存取数,注HibernateSessionFactory.getSession()方法取当前线程对应的Session,这样session3和session2是同一个session才导致这样的问题--2011-12-13
Hibernate: update cui_user set name=? where id=?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值