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

Java 模擬 Hibernate 一級快取機制實作教學

     編輯:Java 相關知識

深入理解 Hibernate 一級快取原理與手工實作

Hibernate 一級快取(Session 級快取)是預設啟用的交易級快取機制。本範例使用純 Java 程式碼模擬其核心運作邏輯:同一 Session 內重複查詢相同 ID 實體時,直接從快取回傳,避免重複資料庫存取。

核心概念解析

  • 快取鍵值:實體 ID(主鍵)作為 Key,實體物件作為 Value
  • 快取範圍:Session 級別,交易結束時清除
  • 查詢流程:先檢查快取 → 快取未命中則查詢資料庫 → 存入快取 → 回傳結果

完整程式碼實作

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 模擬 Hibernate 一級快取機制
 */
public class LevelOneCacheDemo {
    
    // 模擬 Session 級快取:Map<實體ID, 實體物件>
    private static Map cache = new HashMap<>();

    public static void main(String[] args) {
        // 測試連續查詢相同 ID
        getStudent(1);  // 第一次:從資料庫載入
        getStudent(1);  // 第二次:從快取取得
        getStudent(1);  // 第三次:從快取取得
        getStudent(2);  // 第一次:從資料庫載入
        getStudent(2);  // 第二次:從快取取得
    }

    /**
     * 取得學生實體(含快取邏輯)
     * @param id 學生 ID
     * @return Student 物件
     */
    public static Student getStudent(Integer id) {
        // 1. 檢查快取
        if (cache.containsKey(id)) {
            System.out.println("【快取命中】從快取取得資料:ID=" + id);
            return cache.get(id);
        } 
        
        // 2. 快取未命中,查詢資料庫
        System.out.println("【快取未命中】從資料庫查詢資料:ID=" + id);
        Student student = MockDatabase.getStudentById(id);
        
        // 3. 存入快取
        if (student != null) {
            cache.put(id, student);
        }
        return student;
    }
}

/**
 * 模擬資料庫存取層
 */
class MockDatabase {
    private static List database = new ArrayList<>();
    
    static {
        // 初始化模擬資料
        database.add(new Student(1, "張三"));
        database.add(new Student(2, "李四"));
        database.add(new Student(3, "王五"));
    }
    
    public static Student getStudentById(Integer id) {
        for (Student s : database) {
            if (s.getId().equals(id)) {
                return s;
            }
        }
        return null; // 查無資料
    }
}

/**
 * 學生實體類別(POJO)
 */
class Student {
    private Integer id;
    private String name;
    
    public Student() {}
    
    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    @Override
    public String toString() {
        return "Student{id=" + id + ", name='" + name + "'}";
    }
}

執行結果分析

【快取未命中】從資料庫查詢資料:ID=1
【快取命中】從快取取得資料:ID=1
【快取命中】從快取取得資料:ID=1
【快取未命中】從資料庫查詢資料:ID=2
【快取命中】從快取取得資料:ID=2

進階延伸:真實 Hibernate 環境中的注意事項

  1. 快取一致性:同一 Session 內修改實體後,快取會同步更新;但跨 Session 需依賴二級快取
  2. 快取清除:session.clear() 強制清空一級快取;session.evict(entity) 移除特定實體
  3. 查詢快取:HQL/JPQL 查詢結果不預設走一級快取,需啟用查詢快取
  4. 記憶體管理:大量實體載入可能導致 OOM,需合理設計分頁與快取策略

最佳實踐建議

  • 善用 session.get() 而非 session.load() 以利用快取
  • 避免在單一 Session 載入過多實體,適時清除快取
  • 唯讀資料考慮啟用二級快取(Ehcache/Redis)提升效能
  • 分散式環境下需處理快取一致性問題
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved