Hibernate的二级缓存攻略

1.声明:该文章转帖于:http://www.iteye.com/topic/18904

 

 

2.Class的缓存

   对于一条记录,也就是一个PO(Persient Object)来说,是根据ID来查找的,缓存的Key就是ID,value就是POJO。无论list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate会先取数据库的select id出来,然后一个id一个id地load,如果在缓存里面有,就从缓存取,没有的话就去数据库load。假设是读写,则需要设置:

<cache usage="read-write"/>(这是是在*.hmb.xml中设置,位于id属性之前,class属性之后)

 

同时需要ehcache.xml(放置到classpath目录下)

<cache name="com.skywin.simpass.db.domain.PartnerInfo"
            maxElementsInMemory="10000"

            eternal="false"

            timeToIdleSeconds="120"
            timeToLiveSeconds="360"

            overflowToDisk="false" />

 

其中:

     eternal表示的是:缓存是不是永远不过期。(关于过期时间的判断是由  org.hibernate.cache.UpdateTimestampsCache时间戳决定的)

 

     timeToLiveSeconds表示的是:缓存中每个元素(这里也就是一个POJO)的超时时间,如果eternal设定是false的话,超过指定的时间,这个元素就被移走。

 

     timeToIdleSeconds指的是:空闲时间(暂时没有搞定这个东西)

 

每个需要缓存的class都要这样配置。如果没有配置,hibernate会在启动时警告你,然后使用defaultCache的配置,这样多个class会共享一个配置。

     (关于Hibernate的ehcach.xml二级缓存配置,详见附件)

 

      当某个ID通过Hibernate修改时,Hibernate会知道,于是先移除缓存。

 

 

3.查询缓存

   首先要配置:hibernate.cache.use_query_cache=true(在hibernate.cfg.xml或者spring的applicationContext.xml的bean id="sessionFactory"中为其声明)。

 

   其次配置StandardQueryCache

   <cache name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
        timeToLiveSeconds="360" overflowToDisk="false" />

 

   然后使用Query接口的setCacheable(true);//激活查询缓存

   query.setCacheRegion("myCacheRegion"); //指定要使用的cacheRegion,options

 

  ( 哈哈,一般我都不习惯使用这个东西)

  <cache name="myCacheRegion"
        maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
        timeToLiveSeconds="360" overflowToDisk="false" />

 

   对于查询缓存来说,缓存Key是根据hql生成的sql,再加上参数,分页等信息。

   比如hql:

   from Cat c where c.name like ? (Query接口默认的是select 操作)

 

   生成的sql语句大致如下:

   select * from cat c where c.name like ?

   参数是"tiger%",那么查询缓存的key大致会组装成这样子的:

   select * from cat c where c.name like ?, parameter: tiger%

 

   这样,保证了同样的查询,同样的参数等条件下具有一样的key。

 

   现在说说缓存的value,如果是list方式的话,Value在这里并不是整个结果集,而是查询出来的这一串ID。也就是说,不管是list方法还是iterate方法,第一次查询的时候,它们的查询方式和它们平时的方式是一样的,list执行一条sql,iterate执行1+N条,多出来的行为是它们填充了缓存。

 

当hibernate更新数据库的时候,它怎么知道更新哪些查询缓存呢?
hibernate在一个地方维护每个表的最后更新时间,其实也就是放在上面org.hibernate.cache.UpdateTimestampsCache(Hibernate 2.0版本是net.sf)所指定的缓存配置里面。
当通过hibernate更新的时候,hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时 间和这个缓存所查询的表,当hibernate查询一个缓存是否存在的时候,如果缓存存在,它还要取出缓存的生成时间和这个缓存所查询的表,然后去查找这 些表的最后更新时间,如果有一个表在生成时间后更新过了,那么这个缓存是无效的。
可以看出,只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。

 

 

4.Collection缓存

   需要在*.hbm.xml的collection(set/bag/...)里面设置

   <cache usage="read-write"/>

 

 

   同时,需要在ehcache.xml中增加

   <cache name="...Cat.children"

               .../>

 

   Collection的缓存和前面查询缓存的list一样,也是只保持一串id,但是它不会因为这个表更新过就失效,一个collection缓存仅在这个collection里面的元素有增删时才失效。

 

 

 

 

 

 

 

 

 

 

发布了38 篇原创文章 · 获赞 0 · 访问量 1746
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章