Hibernate 二級緩存 1

hibernate3.2二級緩存的配置及測試(ehcache)

 

<script></script>
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,無法判斷是否使用二級緩存。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章