首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 3二級緩存與查詢緩存配置實戰:EhCache整合、註解映射、單元測試驗證

     編輯:Java 相關知識

環境準備:EhCache配置文件

文件名ehcache.xml放置於classpath根目錄(src/main/resources)。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <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"
    />
    <!-- 查詢緩存必備區域 -->
    <cache name="org.hibernate.cache.StandardQueryCache"
           maxElementsInMemory="50"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="7200"
           overflowToDisk="true"/>
    <cache name="org.hibernate.cache.UpdateTimestampsCache"
           maxElementsInMemory="5000"
           eternal="true"
           overflowToDisk="true"/>
</ehcache>
關鍵點:
1. 實體緩存名稱必須與實體全限定名完全一致,否則測試時拋出Cache is not alive異常。
2. UpdateTimestampsCache必須eternal="true",防止時間戳被淘汰導致查詢緩存永不過期。
3. 不建議依賴defaultCache,顯式配置每個實體/集合緩存區域。

實體映射配置:XML與註解雙模式

模式一: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"/>
        </id>
        <property name="field1" type="java.lang.String"/>
        <property name="field2" type="java.lang.String"/>
    </class>
</hibernate-mapping>

模式二:JPA註解(Hibernate 3.5+ / JPA 2.0)

@Entity
@Table(name = "TESTTABLE")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) // 關鍵註解
public class ExampleForTest implements Serializable {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    @Column(name = "id", length = 32)
    private String id;

    @Column(name = "field1")
    private String field1;

    @Column(name = "field2")
    private String field2;
    // getter/setter省略
}

Hibernate配置啟用緩存

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>

單元測試驗證緩存生效

繼承AbstractTransactionalDataSourceSpringContextTests(Spring 2.5/3.x測試基類),事務自動回滾,數據隔離。

public class SecondLevelCacheTest extends AbstractTransactionalDataSourceSpringContextTests {
    @Autowired
    private SessionFactory sessionFactory;

    @Test
    public void testSecondLevelCache() {
        // 1. 首次查詢:觸發SQL,填充二級緩存
        Session s1 = sessionFactory.openSession();
        ExampleForTest e1 = (ExampleForTest) s1.get(ExampleForTest.class, "known-id");
        assertNotNull(e1);
        s1.close();

        // 2. 統計驗證:二級緩存命中數應為1
        Statistics stats = sessionFactory.getStatistics();
        stats.setStatisticsEnabled(true);
        long cacheHitBefore = stats.getSecondLevelCacheHitCount();
        
        // 3. 二次查詢:同一SessionFactory,不同Session
        Session s2 = sessionFactory.openSession();
        ExampleForTest e2 = (ExampleForTest) s2.get(ExampleForTest.class, "known-id");
        assertNotNull(e2);
        s2.close();

        long cacheHitAfter = stats.getSecondLevelCacheHitCount();
        assertEquals(1, cacheHitAfter - cacheHitBefore); // 驗證命中+1
    }

    @Test
    public void testQueryCache() {
        // 啟用查詢緩存
        Query query = sessionFactory.getCurrentSession()
            .createQuery("from ExampleForTest")
            .setCacheable(true); // 關鍵!
        
        List list1 = query.list(); // 首次查詢
        Query query2 = sessionFactory.getCurrentSession()
            .createQuery("from ExampleForTest")
            .setCacheable(true);
        List list2 = query2.list(); // 二次查詢
        
        Statistics stats = sessionFactory.getStatistics();
        stats.setStatisticsEnabled(true);
        assertEquals(1, stats.getQueryCacheHitCount()); // 查詢緩存命中
    }
}

常見配置錯誤與異常分析

異常/現象根因修正
org.hibernate.cache.CacheException: ... Cache is not aliveehcache.xml中實體緩存name與實體全限定名不一致,或漏配實體緩存導致回退defaultCache(多實體共享defaultCache在事務測試中會被關閉)ehcache.xml顯式配置<cache name="實體全限定名" .../>
查詢緩存不生效(每次都執行SQL)1. 未設置setCacheable(true) 2. 實體未配置<cache/> 3. UpdateTimestampsCache配置錯誤檢查三處配置,啟用Hibernate統計觀察QueryCacheHitCount
數據不一致(讀到舊值)1. 緩存策略不當(read-only用於寫入實體) 2. 外部系統直接改庫未同步緩存 3. Class緩存TTL < Query緩存TTL導致1+N查詢讀到中間態按業務選擇策略、外部寫入需手動evict、確保Class TTL ≥ Query TTL
集合緩存順序錯誤集合帶order-by,元素排序字段更新未觸發集合緩存失效避免緩存帶排序集合,或更新排序字段後手動evictCollection

測試環境依賴提示

  • Spring測試基類要求applicationContext-test.xml配置dataSource、sessionFactory、transactionManager。
  • 數據庫建議用H2/Derby內存數據庫加速測試,或MySQL/PostgreSQL獨立Schema。
  • 測試方法按需加@Rollback(true)(默認回滾),保證數據隔離。

總結

Hibernate 3二級緩存配置核心在於:實體緩存名稱精確匹配、UpdateTimestampsCache永久存活、Class緩存TTL不短於Query緩存、顯式聲明緩存策略。結合Spring測試框架與Hibernate Statistics API,可實現緩存行為的自動化驗證,將配置錯誤前移到測試階段發現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved