`
diaolanshan
  • 浏览: 173122 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

hibernate缓存

阅读更多

hibernate缓存

      1、hibernate 的一级缓存是由session提供的,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了。

      2、二级缓存是SessionFactory级别的全局缓存,只要sessionFactory没有关闭,hibernate会首先考虑去缓存中load数据,如果缓存中不存在我们想要的数据或者只有一部分我们想要的数据,hibernate才会去数据库里load数据。它可以利用不同的缓存类库(hibernate本身不提供现成的),比如ehcache、oscache等。需要设置  hibernate.cache.provider_class,我们这里用ehcache,
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider, 

在要缓存的类的配置文件中指定缓存的策略

 <cache usage="read-write"/>(我一般都用这个模式)

如果使用查询缓存,加上 hibernate.cache.use_query_cache=true

设置ehcache.xml,配置如下:

<ehcache>

<diskStore path="C:\\temp"/>

<defaultCache

     maxElementsInMemory="10000"

     eternal="false"

     timeToIdleSeconds="120"

     timeToLiveSeconds="120"

     overflowToDisk="true" />

 

  <cache name="com.eric.model.Customers"

     maxElementsInMemory="1"

    eternal="false"

    timeToIdleSeconds="300"

    timeToLiveSeconds="600"

    overflowToDisk="true" />

 

  <cache name="com.eric.model.Order" 

     maxElementsInMemory="10000"

     eternal="false"

     timeToIdleSeconds="300"

     timeToLiveSeconds="600"

     overflowToDisk="true" />

 <cache name="customerQueries"

      maxElementsInMemory="1000"

      eternal="false"

      timeToIdleSeconds="300"

      timeToLiveSeconds="600"

      overflowToDisk="true" />

 </ehcache>

 

  如果没有对某个具体的类做相应的策略指定,会默认使用defaultCache的配置。
 如果要指定缓存的策略,需要在每次查询之后加上query.setCacheRegion("customerQueries")

 

     1.Class的缓存:对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate会先取数据库select id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有的话就去数据库load。

      2.查询缓存:只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。

 

      先来考察一下缓存的作用:缓存之所以可以命中,前提条件是该数据被使用的非常频繁,同时更新的可能性相当小,如果数据会频繁修改,那么毫无疑问,缓 存不会带来任何好处。明确了这一点,我们就明白什么对象应该进行缓存了。显然,对于那些经常会被访问到的小批量的诸如基础信息,用户和权限信息是非常适合进行缓存的,这些数据我们可以在应用启动的时候就执行一次list方法查询, 进行缓存填充(例如写一个InitBean类进行数据缓存初始化),此外在数据被修改的时候,再次执行list方法,进行缓存填充。而在使用这些数据的其他地方,统统使用iterator方法。这样就可以实现所谓的第一次查询使用 List,随后的查询使用iterator了。

 

      Hibernate在进行批处理的时候存在一定的劣势(很大的劣势),比如在批处理的时候hibernate无法用一条语句来完成,只能以一个实体为单位进行处理,如果要更新一万条数据就要查出一万次,然后update一万次。另外因为hibernate存在缓存机制,load出来的数据会存放在缓存中,而一级缓存我们无法程序控制,这也带来了一些系统开销,这也是hibernate在批处理的时候存在劣势的原因。这种情况下存在几种解决方式:

 

       1)立即flush缓存,然后利用session的evit使对象移除(治标不治本)。

 

       2)利用jdbc实现(hibernate转jdbc还是比较容易的)。

 

       3)建存储过程。

 

hibernate的缓存策略(抄来的) 
只读缓存(read-only):没有什么好说的
读/写缓存(read-write):程序可能要的更新数据
不严格的读/写缓存(nonstrict-read-write):需要更新数据,但是两个事务更新同一条记录的可能性很小,性能比读写缓存好
事务缓存(transactional):缓存支持事务,发生异常的时候,缓存也能够回滚,只支持jta环境,这个我没有怎么研究过

读写缓存和不严格读写缓存在实现上的区别在于,读写缓存更新缓存的时候会把缓存里面的数据换成一个锁,其他事务如果去取相应的缓存数据,发现被锁住了,然后就直接取数据库查询。
在hibernate2.1的ehcache实现中,如果锁住部分缓存的事务发生了异常,那么缓存会一直被锁住,直到60秒后超时。
不严格读写缓存不锁定缓存中的数据。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics