hibernate3.2二级缓存的配置及测试(ehcache)

做删除操作时系统报错:Cache is not alive.
然后找到了这篇文章:研究了下,好了

1.配置ehcache.xml文件,放到classpath下:



<?xml version="1.0" encoding="GBK"?>
      <ehcache>       
             <diskStore path="D://TempObject"/>             
             <defaultCache                      
                       maxElementsInMemory="10000"                     
                       eternal="false"                       
                       timeToIdleSeconds="100"                 
                       timeToLiveSeconds="1000"             
                      overflowToDisk="true"           
              />          
             <cache name="com.sitechasia.occ.core.base.ExampleForTest"                                                                                    maxElementsInMemory="10000"                      
                      eternal="false"                      
                      timeToIdleSeconds="100"                     
                      timeToLiveSeconds="1000"                      
                      overflowToDisk="true"               
               />  
    </ehcache>
建议自定义cache时,cache名字和类路径名相同。
(1)不要使用默认缓存策略defaultCache(多个class共享)
(2)不要给cache name另外起名
否则继承AbstractTransactionalDataSourceSpringContextTests做测试时,抛出
org.hibernate.cache.CacheException: java.lang.IllegalStateException: The com.sitechasia.occ.core.base.ExampleForTest Cache is not alive.( 我注释了红色的cache,使用defaultCache导致

2.在ExampleForTest.hbm.xml中添加:(如果有集合,也需要添加)

<hibernate-mapping>
    <class name="com.sitechasia.occ.core.base.ExampleForTest"
        table="TESTTABLE" lazy="false">
       <cache usage="read-write"/>        <id name="id" type="java.lang.String">
            <column name="id" length="32" />
            <generator class="uuid"></generator>
        </id>
        <property name="field1" type="java.lang.String" />
        <property name="field2" type="java.lang.String" />
    </class>
</hibernate-mapping>
如果使用Annocation,则类前添加
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Proxy(lazy = false)


3.在spring.xml中添加:
<property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!--  使用hibernate自带cache,适合测试用
                    <prop key="hibernate.cache.provider_class">
                          org.hibernate.cache.HashtableCacheProvider
                    </prop>
                -->
                <!--  使用ehcache,适合项目用 -->
                <prop key="hibernate.cache.provider_class">
                    org.hibernate.cache.EhCacheProvider
                </prop>
                <!--  打开hibernate统计功能,我们测试中使用hibernate的统计类-->
                <prop key="hibernate.generate_statistics">true</prop>
                <!--  最优化二级缓存-->
                <prop key="hibernate.cache.use_structured_entries">
                    true
                </prop>
                <!-- 完全禁用二级缓存开关,对那些在类的映射定义中指定cache的类,默认开启二级缓存-->
                <prop key="cache.use_second_level_cache">true</prop>
                <!-- prop key="hibernate.hbm2ddl.auto">create</prop>
                    <prop key="hibernate.default_schema">
                    ${dbunit.schema}
                    </prop>
                -->
            </props>
        </property>
4.配置完了,我们可以测试了:
测试类继承spring的测试组件AbstractTransactionalDataSourceSpringContextTests类;
先初始化数据:
private ExampleForTest example1, example2;
public void onSetUpBeforeTransaction() {
        example1 = new ExampleForTest();
        example1.setField1("param1");
        example1.setField2("param2");
        example2 = new ExampleForTest();
        example2.setField1("attribute1");
        example2.setField2("attribute2");
    }
再写测试方法:
exampleDao中有2个方法:
(1)list方式获取参数:(对二级缓存只写不读)
exampleDao.findByHQL(hql);
(2)iterate方式获取参数:(对二级缓存可写可读)
exampleDao.cacheByHQL(hql);
测试(2)方法:
public void testCacheByHQL() {

        /**先打开注释,往数据库增加2条数据,然后关闭
        exampleDao.save(example1);
        exampleDao.save(example2);
        setComplete();
        */
        String hql = "from ExampleForTest";
        //List list = exampleDao.findByHQL(hql); //开关控制
        List<ExampleForTest> iterate = exampleDao.cacheByHQL(hql);
        Statistics statistics = sessionFactory.getStatistics();
        // 统计entity信息
        for (int i = 0; i < statistics.getEntityNames().length; i++) {
            String entityName = statistics.getEntityNames()[i];
            System.out.println("entityName:" + entityName);
            EntityStatistics entityStatistics = statistics
                    .getEntityStatistics(entityName);
            System.out.println("entityStatistics:" + entityStatistics);
        }
        assertEquals(2, iterate.size());
    }
1》注释开关控制代码行,iterate获取数据,发现有N+1问题,说明是从数据库读取的数据,日志如下:
Hibernate: select examplefor0_.id as col_0_0_ from TESTTABLE examplefor0_
Hibernate: select examplefor0_.id as id0_0_, examplefor0_.field1 as field2_0_0_, examplefor0_.field2 as field3_0_0_ from TESTTABLE examplefor0_ where examplefor0_.id=?
Hibernate: select examplefor0_.id as id0_0_, examplefor0_.field1 as field2_0_0_, examplefor0_.field2 as field3_0_0_ from TESTTABLE examplefor0_ where examplefor0_.id=?
entityName:com.sitechasia.occ.core.base.ExampleForTest
entityStatistics:EntityStatistics[loadCount=2,updateCount=0,insertCount=0,deleteCount=0,fetchCount=2,optimisticLockFailureCount=0]
2》打开开关控制代码行注释,先list方式读取数据,会写入二级缓存,再用iterate获取数据时,发现没有了N+1问题,说明是从二级缓存中读取的数据,日志如下:
Hibernate: select examplefor0_.id as id0_, examplefor0_.field1 as field2_0_, examplefor0_.field2 as field3_0_ from TESTTABLE examplefor0_
Hibernate: select examplefor0_.id as col_0_0_ from TESTTABLE examplefor0_
entityName:com.sitechasia.occ.core.base.ExampleForTest
entityStatistics:EntityStatistics[loadCount=2,updateCount=0,insertCount=0,deleteCount=0,fetchCount=0,optimisticLockFailureCount=0]

5.需要注意的是,实体映射文件中lazy=false必须设置,即立即加载;否则后台日志不打印那N条通过id获取实体的sql,无法判断是否使用二级缓存。




name:缓存名称。
       maxElementsInMemory:缓存最大个数。
       eternal:对象是否永久有效,一但设置了,timeout将不起作用。
       timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
       timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
       overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
       diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
       maxElementsOnDisk:硬盘最大缓存个数。
       diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
       diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
       memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
       clearOnFlush:内存数量最大时是否清除。

猜你喜欢

转载自liyn2008.iteye.com/blog/1623990