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

Hibernate整合EhCache實現二級緩存與查詢緩存完整配置指南

     編輯:Java 相關知識

快速啟動:四步完成核心配置

步驟1:編寫ehcache.xml放入classpath根目錄(如src/main/resources)

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
    />
    <!-- 實體專用緩存建議顯式配置,名稱=實體全限定名 -->
    <cache name="com.example.entity.User"
           maxElementsInMemory="5000"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           overflowToDisk="true"/>
    <!-- 集合緩存示例 -->
    <cache name="com.example.entity.User.roles"
           maxElementsInMemory="2000"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           overflowToDisk="true"/>
</ehcache>

步驟2:Hibernate配置文件啟用二級緩存與查詢緩存

<!-- hibernate.cfg.xml 或 Spring LocalSessionFactoryBean配置 -->
<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>
<!-- 可選:指定查詢緩存工廠 -->
<property name="hibernate.cache.query_cache_factory">org.hibernate.cache.StandardQueryCacheFactory</property>

步驟3:實體映射文件聲明緩存策略

<hibernate-mapping>
    <class name="com.example.entity.User" table="SYS_USER">
        <cache usage="read-write"/>
        <id name="id"><generator class="native"/></id>
        <property name="username"/>
        <set name="roles" table="USER_ROLE">
            <cache usage="read-write"/>
            <key column="user_id"/>
            <many-to-many class="com.example.entity.Role" column="role_id"/>
        </set>
    </class>
</hibernate-mapping>

步驟4:代碼中啟用查詢緩存

// HQL查詢
Query query = session.createQuery("from User u where u.username like ?");
query.setParameter(0, "admin%");
query.setCacheable(true); // 關鍵!
query.setCacheRegion("userQueryRegion"); // 可選:使用自定義區域
List<User> list = query.list();

// Criteria查詢
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.like("username", "admin%"));
criteria.setCacheable(true); // 關鍵!
List<User> list2 = criteria.list();

Spring整合配置示例

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingDirectoryLocations">
        <list><value>classpath:com/example/entity/</value></list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
        </props>
    </property>
</bean>

驗證緩存生效:測試代碼模板

public class CacheTest {
    public static void main(String[] args) {
        Session s = HibernateSessionFactory.getSession();
        Criteria c = s.createCriteria(User.class);
        c.setCacheable(true);
        List<User> l1 = c.list();
        User u1 = l1.get(0);
        System.out.println("第一次查詢: " + u1.getUsername());
        HibernateSessionFactory.closeSession();

        try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }

        s = HibernateSessionFactory.getSession();
        c = s.createCriteria(User.class);
        c.setCacheable(true);
        List<User> l2 = c.list();
        User u2 = l2.get(0);
        System.out.println("第二次查詢: " + u2.getUsername());
        // 控制台若無Hibernate SQL輸出,說明查詢緩存命中
        HibernateSessionFactory.closeSession();
    }
}
觀察控制台SQL輸出:第一次查詢有select ... from SYS_USER,第二次查詢無SQL輸出即代表查詢緩存命中(同時Class緩存也命中)。

關鍵區別澄清:load() vs list()/iterate()/criteria.list()

方法默認使用二級緩存需額外配置
session.load/get()是(Class緩存)無
session.find/list/iterate()否setCacheable(true) + 實體配置<cache/>
Query.list/iterate()否setCacheable(true) + 實體配置<cache/>
Criteria.list()否setCacheable(true) + 實體配置<cache/>

結論:只有load/get自動受益於Class緩存。所有列表查詢必須顯式setCacheable(true)才能使用查詢緩存,並依賴Class緩存組裝對象。

常見配置錯誤自查清單

  1. ehcache.xml未放入classpath:打包後確認在WEB-INF/classes或jar包根目錄。
  2. 實體緩存名稱不匹配:<cache name="..."/>必須等於實體全限定名(或集合角色名)。
  3. 查詢緩存區域未配置:使用setCacheRegion("custom")時,ehcache.xml必須有同名<cache>定義。
  4. UpdateTimestampsCache配置缺失或eternal=false:導致查詢緩存永不過期或異常失效。
  5. Class緩存TTL短於Query緩存TTL:引發1+N查詢,詳見「Hibernate二級緩存深度解析」一文。

進階優化建議

  • 區域劃分:核心高頻實體獨立區域(長TTL、大內存),邊緣低頻實體共享defaultCache。
  • 只讀實體用read-only:字典、編碼表等極少變更數據,性能最高。
  • 監控指標:通過EhCache JMX或Hibernate統計接口(sessionFactory.getStatistics())監控命中率、內存佔用、淘汰率。
  • 集群環境:單機EhCache無法同步,需遷移至Terracotta BigMemory、Hazelcast、Infinispan等分布式緩存實現。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved