在實際專案中,大量查詢操作針對的是相對靜態的共用數據(如字典表、配置資訊、熱門商品等)。若每次請求都直擊資料庫,不僅增加資料庫負載,嚴重影響系統響應速度。MyBatis 的二級緩存(Second Level Cache)恰好解決此痛點:它作用於 SqlSessionFactory 範圍,多個 SqlSession 可共享緩存數據,大幅降低資料庫訪問頻率。
在 Mapper 映射文件中添加一行即可開啟預設二級緩存:
<cache />
預設行為如下:
select 語句自動緩存insert、update、delete 執行時自動刷新緩存read/write),返回對象副本,線程安全透過 <cache> 元素屬性可精確控制緩存行為:
<!-- 1 小時刷新一次,FIFO 策略,容量 512,唯讀模式 -->
<cache eviction="FIFO"
flushInterval="3600000"
size="512"
readOnly="true"/>
| 屬性 | 說明 | 可選值 / 預設值 |
|---|---|---|
eviction | 淘汰策略 | LRU(預設)、FIFO、SOFT、WEAK |
flushInterval | 刷新間隔(毫秒) | 正整數,預設無間隔 |
size | 最大引用數量 | 正整數,預設 1024 |
readOnly | 是否唯讀 | true/false(預設 false) |
關鍵取捨:
readOnly="true"):直接返回緩存對象引用,效能最高,但調用者絕不可修改對象,否則引發併發問題。readOnly="false"):返回序列化後的對象副本,較慢但安全,適合需修改返回對象的場景。實際開發中,並非所有查詢適合緩存,非所有寫操作需刷新緩存。MyBatis 提供語句級屬性:
select 設定 useCache="false" → 跳過二級緩存,直接查庫insert/update/delete 設定 flushCache="false" → 執行後不刷新緩存<select id="selectRealTimeData" resultType="Data" useCache="false">
SELECT * FROM real_time_table WHERE id = #{id}
</select>
<update id="updateLog" flushCache="false">
INSERT INTO operation_log (...) VALUES (...)
</update>
flushInterval,避免長時間髒讀;高頻更新表建議關閉二級緩存或縮短間隔。CacheRef 跨命名空間共享緩存時,需特別注意一致性。MyBatis 二級緩存配置極簡,核心在於理解預設行為、按業務調整屬性、語句級精細控制。善用它能顯著降低資料庫壓力,但切忌濫用——對於強一致性、高頻寫入場景,直接查庫或引入分散式緩存才是正道。