Hibernate 一級快取(Session 級快取)是預設啟用的交易級快取機制。本範例使用純 Java 程式碼模擬其核心運作邏輯:同一 Session 內重複查詢相同 ID 實體時,直接從快取回傳,避免重複資料庫存取。
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
session.clear() 強制清空一級快取;session.evict(entity) 移除特定實體session.get() 而非 session.load() 以利用快取