Hibernate3二级缓存Roy说明

以下测试均是在Hibernate3.64(最新版)和Ehcache2.3.3环境下进行的:

开启查询缓存及二级缓存的配置说明:
1.hibernate.cfg.xml 或者 applicationConten.xml(与Spring集成的环境下)添加下面几个属性:
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定二级缓存提供商驱动 -->
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

2.在各个对应的dto对象中如果要使用缓存请在<class>子标签下或关联子对象(Set list)里加:<cache usage="read-write"/>
3.代码中在查询数据时请添加以下二句:
query.setCacheable(true);     //说明使用查询缓存
query.setCacheRegion("Role"); //指定使用的自定义缓存名字(如果不指定则使用默认的缓存规则),在ehcache.xml里应有对应的配置

4.ehcache.xml文件配置:
<ehcache>
<diskStore path="java.io.tmpdir"/>
<!-- 默认缓存,必须要有的。-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
        />
<!-- 自定义的缓存 -->
<cache name="Role"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
        />


使用中发现的限制条件如下:
1.对对象的get(id)操作会先读缓存再查数据库,修改后并同步更新缓存。
2。针对条件查询的HQL 是可以使用二级缓存的,和没有条件的 from DTO;是一样的(基于最新版本测试的)。
2.query.list
不会有n+1的问题,一次性读出所以的记录。如果配置了二级缓存会先从缓存中取
但只要对同一张表有任何记录的更改, 即使改的不属于list条件内的记录,整个list缓存也会失效(这样很不好)。
只要查询的hql 有任何变化:哪怕没有实质性的变化如  and 1=1 则,list的缓存也会失效。

3.query.iterate
虽然有著名的n+1问题, 即先查出满足条件的所有id集合, 再根据n条id发出n条SQL语句。如果配置了二级缓存会先从二级缓存中查。
但是对表记录的更改包括对list集合里的记录更改都不会造成整个缓存的失效(这个是我们想要的)。原理与query.list不同,
所以不会有失效问题。
每次使用都会发出1条SQL语句去查ID集合的。

4。网上有人说批处理时不会更新缓存是不准确的, 执行批处理后,list的缓存会失效,但iterate不会失效,也不同步,即出现了
   脏数据(很可怕的)。

5. 查看二级缓存的操作过程
      调试时候,可以设置log4j的log4j.logger.org.hibernate.cache=debug(记录第二级缓存的活动),更方便看到ehcache的操作过程。用于调试过程,实际应用发布时候,请注释掉,以免影响性能。在log4j.properties文件中添加如下内容:
log4j.logger.org.hibernate.cache=debug

6. SessionFactory提供了查看二级缓存中的数据的方法:
Map cacheEntries = sessionFactory.getStatistics()
.getSecondLevelCacheStatistics(“cacheRegionName”)
.getEntries();      

7. 一级缓存与二级缓存的几种交互模式,分别用org.hibernate.CacheMode类的5个静态常量表示。
CacheMode.NORMAL  :从二级缓存读写数据(默认模式)
CacheMode.GET  :读取模式,从二级缓存读数据
CacheMode.PUT  : 写入模式,仅向二级缓存写数据,但不从二级缓存读数据
CacheMode.IGNORAL  :忽略模式,不会从二级缓存中读取数据,也不会向其中写入数据。
CacheMode.REFRESH  :刷新模式,Session不会从二级缓存中读取数据,但会向其中写入从数据库中读到的数据。
Session接口设置交互模式的方法session.setCacheMode();
       session = sessionFactory.openSession();
        //设置了不把数据放入二级缓存,仅从二级缓存读数据
        session.setCacheMode(CacheMode.GET);
        tx = session.beginTransaction();
       Dept dept = (Dept)session.get(Dept.class,"001");
       System.out.println(dept.getDeptName());
       //查询出来后没有放入二级缓存
       session.getTransaction().commit();
       session.close();



总结:H的二级缓存不太理想,最好是使用到很少被修改的数据表上。失效策略太差了。

你可能感兴趣的:(spring,sql,xml,Hibernate,cache)