ORM 框架的快取設計直接決定資料庫存取效能。本文深度剖析 Hibernate (二級快取 + 查詢快取) 與 Jive (ID 導向快取) 的核心機制、優劣勢對比與適用場景,助你做出架構選型決策。
核心概念釐清
- PO (Persistent Object):持久化物件,對應資料表列。
- VO (Value Object):業務領域物件,承載業務邏輯。
- FormBean:Web 表單封裝,屬控制層關注點。
Jive 快取策略:ID 導向的精準命中
運作流程
- 條件查詢:先執行
SELECT id FROM table WHERE ... 取得 ID 列表 (單次 DB 存取)。
- ID 逐筆解析:遍歷 ID 列表,優先查快取 → 命中直接回傳 → 未命中執行
SELECT * FROM table WHERE id = ? 查詢完整物件,存入快取並加入結果集。
- 單一 ID 查詢:同樣快取優先,未命中再查 DB。
- 寫入同步:增刪改同步更新快取。
優勢
- ID 查詢極致命中,省去 DB 往返。
- 多次條件查詢結果集有交集時,交集物件直接從快取取得,避免重複完整物件查詢。
劣勢
- 條件查詢 必須 執行首輪 ID 查詢 (不可省略)。
- 最壞情況 (快取全未命中) 需 N+1 次查詢 (1 次 ID 列表 + N 次完整物件)。
Hibernate 二級快取:SessionFactory 級共享快取
運作流程
- 條件查詢:直接執行
SELECT * FROM table WHERE ... 一次性取得完整物件 (單次 DB 存取,但選取所有欄位)。
- 快取填充:將結果按 ID 存入二級快取 (需配置
hibernate.cache.use_second_level_cache=true 與快取提供者如 Ehcache/Infinispan)。
- ID 查詢:一級快取 → 二級快取 → DB,層層遞進。
- 寫入同步:增刪改同步失效/更新快取。
優勢
- 避免 Jive 的 N+1 最壞情況,條件查詢固定 1 次 DB 存取。
- ID 查詢同樣享受快取命中紅利。
劣勢
- 條件查詢選取所有欄位,網路/記憶體開銷大於 Jive 的純 ID 查詢。
- 條件查詢無法利用快取:即使結果物件已在快取,仍需完整查詢 DB (除非啟用查詢快取)。
Hibernate 查詢快取:條件查詢的終極武器
針對「相同查詢條件重複執行」場景:
- 啟用:
hibernate.cache.use_query_cache=true + 查詢呼叫 setCacheable(true)。
- 機制:以 (查詢語句 + 參數) 為 Key,查詢結果 ID 列表為 Value 存入查詢快取區。
- 執行流程:查詢快取命中 ID 列表 → 逐筆走二級快取/DB 解析完整物件。
- 配合二級快取使用時,重複條件查詢可達 零 DB 存取。
對比總結表
| 維度 | Jive | Hibernate 二級快取 | Hibernate + 查詢快取 |
| 條件查詢 DB 次數 (冷快取) | N+1 | 1 | 1 |
| 條件查詢 DB 次數 (熱快取) | 1 (ID查詢) + 交集命中 | 1 (全欄位查詢) | 0 (全快取命中) |
| ID 查詢快取命中 | 支援 | 支援 | 支援 |
| 交集結果集複用 | 優秀 | 不支援 | 支援 (透過查詢快取) |
| 快取粒度 | 物件級 (按 ID) | 物件級 (按 ID) | 查詢結果級 + 物件級 |
| 配置複雜度 | 低 (內建) | 中 (需整合快取提供者) | 高 (雙快取配置+失效策略) |
選型建議
- Jive 風格:適合「ID 查詢為主、條件查詢結果集重疊率高、資料量中等、團隊偏好輕量框架」的專案。
- Hibernate 二級快取:標準 JPA/ORM 專案首選,配合成熟快取提供者 (Ehcache/Infinispan/Redis),開箱即用。
- Hibernate + 查詢快取:唯一能實現條件查詢零 DB 存取 的方案,適合「高讀低寫、查詢條件固定、資料變更頻率可控」的報表、配置、字典類場景。警示:寫入頻繁時快取失效風暴會拖垮效能,需謹慎評估失效策略與快取容量。
快取非銀彈,關鍵在於 讀寫比例、資料熱度分布、一致性容忍度 的量化分析。建議以監控指標 (命中率、DB QPS、GC 壓力) 驅動快取調優,而非經驗拍板。