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

Hibernate 註解整合 Ehcache 實現二級緩存完整指南

     編輯:J2EE

前言

自 Hibernate 2.1 版本起,Ehcache 已成為 Hibernate 內建的預設二級緩存提供者(SessionFactory 層級)。在專案中針對性地引入緩存機制,能顯著提升系統效能,特別是對於頻繁讀取、較少變動的資料。

整合步驟

1. 引入相依套件

在 classpath 中加入以下 JAR 檔:

  • ehcache-core-xxx.jar (Ehcache 核心庫)
  • commons-logging-xxx.jar (日誌介面)

2. 設定 Hibernate 組態檔 (hibernate.cfg.xml)

在 <session-factory> 標籤內新增下列屬性:

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

注意: 若未啟用 cache.use_second_level_cache (預設為 false),依據 ID 單筆查詢時將不會走二級緩存,導致產生大量重複 SQL。

3. 於實體類別標註緩存策略

使用 JPA 註解 @Cache 指定並發策略,Hibernate 提供五種策略供選擇:

策略適用場景
NONE不啟用緩存 (預設)
NONSTRICT_READ_WRITE資料極少更新 (數小時或更久)
READ_ONLY資料絕不變更 (如字典表、設定檔)
READ_WRITE基於時間戳判定,資料同步要求嚴格且讀寫頻繁
TRANSACTIONAL僅限 JTA 環境,基於事務邊界

範例:將實體標記為唯讀緩存

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class B {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String bname;
    // getter/setter 略
}

4. 撰寫 ehcache.xml 組態檔

置於 classpath 根目錄 (如 src/main/resources):

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="300"
        timeToLiveSeconds="180"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
    />
</ehcache>

關鍵屬性說明:

  • maxElementsInMemory:記憶體中最大物件數
  • eternal:true 表示永不過期,將忽略 timeToIdleSeconds 等屬性
  • overflowToDisk:記憶體不足時是否溢寫至磁碟
  • timeToIdleSeconds:閒置超過秒數後淘汰
  • timeToLiveSeconds:存活超過秒數後淘汰

實戰驗證

基本查詢緩存測試

public static void getTest() {
    Session session = HibernateSessionFactory.getSession();
    Query q = session.createQuery("from B where id > ?");
    q.setParameter(0, 10);
    q.setCacheable(true); // 必須開啟查詢緩存
    List list = q.list();
    for (Object obj : list) {
        B b = (B) obj;
        System.out.print(b.getId() + "/");
    }
    session.close();
}

public static void main(String[] args) {
    getTest(); // 第一次查詢,輸出 SQL
    getTest(); // 第二次查詢,直接走緩存,無 SQL
}

控制台輸出:

Hibernate: select b0_.id as id1_, b0_.bname as bname1_ from B b0_ where b0_.id>?
11/14/18/25/26/27/28/29/
11/14/18/25/26/27/28/29/  <-- 第二次無 SQL,直接從緩存讀取

自訂緩存區域

在 ehcache.xml 中定義專屬 <cache> 節點:

<cache name="cache_a"
    maxElementsInMemory="5"
    eternal="false"
    timeToIdleSeconds="300"
    timeToLiveSeconds="600"
    overflowToDisk="true"
/>

查詢時指定區域:

Query q = session.createQuery("from B where id > ?");
q.setParameter(0, 10);
q.setCacheable(true);
q.setCacheRegion("cache_a"); // 使用自訂區域

觀察磁碟溢寫檔案

預設磁碟路徑為 java.io.tmpdir,可透過 System.getProperty("java.io.tmpdir") 取得實際路徑 (如 C:\DOCUME~1\eric\LOCALS~1\Temp\)。

執行查詢並 Thread.sleep(10000) 等待磁碟寫入後,該目錄下將出現:

  • cache_a.data:自訂區域緩存資料
  • com.eric.po.B.data:實體預設區域 (若未指定自訂區域)
  • org.hibernate.cache.StandardQueryCache.data:查詢緩存資料
  • org.hibernate.cache.UpdateTimestampsCache.data:時間戳緩存 (用於驗證緩存有效性)

總結

透過 @Cache 註解與 ehcache.xml 靈活配置,開發者可輕鬆在 Hibernate 中實現二級緩存與查詢緩存,並依業務特性選擇適當的並發策略,有效降低資料庫負載、提升回應速度。

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