【MyBatis】MyBatis 快取
阿新 • • 發佈:2020-12-19
MyBatis 快取
什麼是快取
像大多數的持久化框架一樣,MyBatis 也提供了快取策略,通過快取策略來減少資料庫的查詢次數,從而提高效能。
Mybatis 中快取分為一級快取,二級快取。
快取的適用範圍
適用範圍:
- 經常查詢並且不經常改變的
- 資料的正確與否對最終結果影響不大
一級快取
它指的是 MyBatis 中 SqlSession 物件的快取,當執行查詢之後,查詢的結果會同時存入到 SqlSession 會提供一塊區域。該區域的結構是一個 Map,當再次查詢同樣的資料,MyBatis 會先去 SqlSession 中查詢是否存在,如果有則直接拿出來使用。
當 SqlSession 物件消失時,MyBatis 的一級快取也就消失了。
一級快取的使用:
-
編寫使用者持久層 DAO 介面
/** * 根據 ID 查詢操作,使用一級快取 * @param id * @return */ User findByIdCache(Integer id);
-
編寫使用者持久層對映檔案
<select id="findByIdCache" resultType="USER" parameterType="java.lang.Integer"> select * from user where id = #{id}; </select>
-
測試
@Test public void findByIdCacheTest() { User user1 = userDAO.findByIdCache(41); System.out.println(user1.hashCode()); // 1439337960 User user2 = userDAO.findByIdCache(41); System.out.println(user2.hashCode()); // 1439337960 System.out.println(user1 == user2); // true }
一級快取的清空:
@Test
public void findByIdCacheClearTest() {
User user1 = userDAO.findByIdCache(41);
System.out.println(user1.hashCode()); // 1439337960
// 使快取消失方法一:關閉 SqlSession 物件
// session.close();
// 使快取消失方法二
session.clearCache();
// session = factory.openSession();
userDAO = session.getMapper(UserDAO.class);
User user2 = userDAO.findByIdCache(41);
System.out.println(user2.hashCode()); // 315860201
System.out.println(user1 == user2); // false
}
一級快取的分析:
- 一級快取是 SqlSession 範圍的快取,當呼叫 SqlSession 的修改,新增,刪除,
commit()
,close()
等方法時,就會清空一級快取。 - 第一次發起查詢使用者 id 為 41 的使用者資訊,先去找快取中是否有 id 為 41 的使用者資訊,如果沒有,從資料庫查詢使用者資訊。
- 得到使用者資訊,將使用者資訊儲存到一級快取中。
- 如果 SqlSession 去執行 commit 操作(執行插入、更新、刪除),清空 SqlSession 中的一級快取,這樣做的目的為了讓快取中儲存的是最新的資訊,避免髒讀。
- 第二次發起查詢使用者 id 為 41 的使用者資訊,先去找快取中是否有 id 為 41 的使用者資訊,快取中有,直接從快取中獲取使用者資訊。
二級快取
它指的是 MyBatis 中 SqlSessionFactory 物件的快取,由同一個 SqlSessionFactory 物件建立的 SqlSession 共享其快取。
二級快取結構圖:
二級快取的使用:
-
在 SqlMapConfig.xml 檔案開啟二級快取
<settings> <!-- 開啟二級快取的支援 --> <setting name="cacheEnabled" value="true"/> </settings>
-
配置相關的 Mapper 對映檔案
<!-- 開啟二級快取的支援 --> <cache></cache>
-
配置 statement 上面的 useCache 屬性
<select id="findByIdHighCache" resultType="USER" parameterType="java.lang.Integer" useCache="true"> select * from user where id = #{id}; </select>
-
測試
@Test public void findByIdHighCacheTest() { SqlSession sqlSession1 = factory.openSession(); UserDAO dao1 = sqlSession1.getMapper(UserDAO.class); User user1 = dao1.findByIdHighCache(41); System.out.println(user1.hashCode()); // 765284253 sqlSession1.close(); // 一級快取消失 SqlSession sqlSession2 = factory.openSession(); UserDAO dao2 = sqlSession2.getMapper(UserDAO.class); User user2 = dao2.findByIdHighCache(41); System.out.println(user2.hashCode()); // 1043351526 sqlSession1.close(); // 一級快取消失 System.out.println(user1 == user2); // false }
測試中執行了兩次查詢,並且在執行第一次查詢後,關閉了一級快取,再去執行第二次查詢時,可以發現並沒有對資料庫發出 SQL 語句,所以此時的資料就只能是來自於所說的二級快取。