簡介
什麼是快取
**將一次查詢的結果暫存至記憶體,後續查詢只需查詢快取**
為什麼使用快取
**減少與資料庫的互動次數,減少系統開銷,提高系統效率**
什麼樣的資料能使用快取
**經常查詢且不常修改的資料**
Mybatis快取
一級快取
也叫本地快取,預設開啟,無法關閉,只在一次SqlSession中有效(拿到連線->關閉連線),底層由【Map】實現資料儲存
- 與資料庫同一次會話期間查詢到的資料會放在本地快取中
- 若之後需要獲取相同資料,直接從快取中獲取
<select id="queryUserById" resultType="User">
SELECT * FROM user WHERE id = #{id};
</select>
<update id="updateUser" parameterType="User">
UPDATE user set name = #{name}, pwd = #{pwd} WHERE id = #{id};
</update>
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
User user2 = mapper.queryUserById(1);
System.out.println(user == user2);
sqlSession.close();
- 日誌輸出SQL語句僅執行一次,且輸出結果為true,表明兩個user例項物件為同一個
sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
User iris = new User(1, "Iris", "123");
mapper.updateUser(iris);
User user2 = mapper.queryUserById(1);
System.out.println(user == user2);
- 在修改資料庫資料(哪怕不是目標記錄)後再次查詢會重新訪問資料庫
【快取失效原因】
- 查詢不同的記錄
- 查詢不同的Mapper
- 不同執行緒查詢
- 增刪改操作均可能導致快取重新整理
- 手動清除
二級快取
需在核心配置檔案中開啟快取【即使預設開啟】,才能手動配置快取屬性
開啟全域性快取(手動顯示開啟)
<setting name="cacheEnabled" value="true"/>
全域性快取,由於一級快取作用域太低從而產生,基於namespace級別的快取,二級快取會將每次會話的一次快取出儲存至二級快取,不同mapper所查詢的資料放在其對應快取【Map】中
二級快取由標籤cache實現,其中可設定相關屬性:
- 快取策略
- LRU【預設】:最近最少使用(移除最長時間不被使用的物件)
- FIFO:先進先出(按物件進入快取的順序來移除它們)
- SOFT:軟引用(基於垃圾回收器狀態和軟引用規則移除物件)
- WEAK:弱引用(更積極地基於垃圾收集器狀態和弱引用規則移除物件)
- 快取重新整理間隔(ms)
- 引用數目【預設為1024個物件】
- 是否僅可讀【預設可讀寫】
下面的示例建立了一個FIFO快取,間隔60重新整理,最多儲存512個物件且返回的物件僅可讀
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
測試二級快取是否有效
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
sqlSession.close();
User user2 = mapper2.queryUserById(1);
System.out.println(user2);
System.out.println(user == user2);
sqlSession2.close();
【結果輸出:true】意為sqlSqssion2在sqlSession關閉後從二級快取中獲取到了sqlSession存入的資料。
報錯【物件未序列】的解決方法
- 例項物件繼承Serializable
public class User implements Serializable
- 設定快取物件僅可讀(mapper.xml中)
readOnly="true"
小結
- 只要開啟二級快取,在相同Mapper下均有效
- 所有資料都會先放在一級快取中
- 只有當會話提交/關閉,資料才轉存至二級快取中