為何需要緩存?
Hibernate 作為持久層框架,頻繁訪問物理數據庫。引入緩存可降低數據庫訪問頻次,提升應用性能。緩存數據為數據庫數據副本,特定時機同步刷新。
兩大緩存層級
1. 一級緩存(Session 級,強制啟用)
- 別名:Session 緩存,內置不可卸載;
- 生命週期 = Session 生命週期(通常對應一個數據庫事務/業務事務);
- 作用域:事務級;
- 特性:持久化類每個實例在 Session 內唯一(OID 唯一);
- 操作:
save()/update()/get()/load() 均觸發一級緩存讀寫。
2. 二級緩存(SessionFactory 級,可選插件)
- 別名:SessionFactory 緩存,進程/集群級;
- 生命週期 = 應用程序全生命週期;
- 并發風險:需配置并發訪問策略(ReadOnly/NonstrictReadWrite/ReadWrite/Transactional)提供事務隔離級別;
- 默認關閉,需顯式啟用並指定實現(EhCache/Infinispan/Redis 等);
- 核心接口:
org.hibernate.cache.CacheProvider 作為適配器。
二級緩存適用性判斷
| ✅ 適合放入二級緩存 | ❌ 不適合放入二級緩存 |
| 極少修改的數據(字典表、配置表) | 頻繁修改的數據(訂單、庫存) |
| 允許偶爾臟讀的非核心數據 | 絕對禁止併發衝突的財務/資金數據 |
| 單線程/單節點獨享數據 | 多應用共享的數據(需分布式鎖或數據庫協調) |
| 常量/引用數據(郵編、國家代碼) | |
Session 延遲加載的兩大前置條件
- 請求結束正確關閉 Session:通過 Filter(OpenSessionInViewFilter)保證 Session 在視圖渲染前不關閉;
- 同一請求復用同一 Session:Session 綁定在
ThreadLocal,確保請求鏈路內獲取同一實例。
本質:Hibernate Session 封裝 java.sql.Connection,一一對應。
對象查找緩存穿透鏈路
- 根據 ID 查找 → 先檢查 一級緩存;
- 未命中 → 若啟用二級緩存 → 檢查 二級緩存;
- 仍未命中 → 發送 SQL 查詢 數據庫;
- 結果寫入一級緩存(若配置則同步二級緩存);
- 增刪改操作 → 同步更新相關緩存層。
最佳實踐建議
- 默認信任一級緩存,二級緩存按需開啟,避免過度緩存導致數據不一致;
- 實體類添加
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 註解啟用二級緩存;
- 查詢緩存(Query Cache)配合二級緩存使用,緩存 HQL/SQL 查詢結果集 ID 列表;
- 集群環境必選分布式緩存實現(Redis/Infinispan),禁用本地 EhCache。