mybatis中的一級快取深入剖析
mybatis中提供有一級快取 和 二級快取,這裡記錄一下一級快取
一級快取(mybatis中預設開啟)
SqlSession級別的快取,操作資料庫時需要構造SQLSession物件, 在物件中有一個數據結構(HashMap)用於儲存快取資料,不同的SQLSession物件之間的快取資料是不共享的,即獨立的
根據第一點,簡單一點講就是一級快取是屬於物件的(個人記法)
從別處搞來一個圖,便於我們理解:
下面用spring整合mybatis來測試一下mybatis的一級快取:
1、下面是service層實現, 可以看到,我兩次查詢了同一個資料,理論上由於mybatis中預設開啟一級快取, 那麼第二次肯定時要從快取中獲取,而不是建立SqlSession物件重新從資料庫獲取
@Autowired private LsjmUserMapper lsjmUserMapper; @Override public LsjmUser getUser() { // 第一次查詢 LsjmUser user = lsjmUserMapper.getUserByName("300"); System.out.println(user.toString()); // 第二次查詢 LsjmUser user1 = lsjmUserMapper.getUserByName("300"); System.out.println(user1.toString()); return user; }
前臺頁面觸發這個service後,控制檯列印:
從日誌資訊可以很明顯的看到,程式碼中的兩次查詢構建了兩個SqlSession物件,也就是說第二次查詢並沒有從前一次的SqlSession快取中獲取,而是自己新建一個SQLSession物件,重新查詢,,看似,mybatis的一級快取失效了?
2、spring 中 結合 mybatis中,預設情況下,資料庫處於自動提交模式,每一條sql語句處於一個單獨的事務中,語句執行完畢時,如果執行成功則隱式提交事務。而mybatis的一級快取在這種情況下是無效的,想要一級快取起作用,則要開啟事務:
開啟事務: spring使用ThreadLocal獲取當前資源繫結同一個SQLSession
未開啟事務:每次查詢,spring關閉舊的SslSession,建立一個新的Sqlsession物件,一級快取補氣作用
下面Service層中的程式碼同樣對同一個資料查詢了兩次,這次開啟了事務管理
@Autowired private LsjmUserMapper lsjmUserMapper; @Override @Transactional // 開啟事務控制,當前,spring配置檔案中得先配置好 public LsjmUser getUser() { // 第一次查詢 LsjmUser user = lsjmUserMapper.getUserByName("300"); System.out.println(user.toString()); // 第二次查詢 LsjmUser user1 = lsjmUserMapper.getUserByName("300"); System.out.println(user1.toString()); return user; }
前臺頁面觸發Service後:控制檯列印日誌:
可以看出來第一次查詢時,構造了一個SqlSession物件,從資料庫查詢資料,然後將查詢的結果儲存到一級快取SqlSession中,第二次查詢時,直接Fetched SqlSession,而不是再重新建一個,此時就是從快取中直接取資料了
開啟事務後取如何取到同一個SqlSession,原始碼解析可以參考這裡:spring結合mybatis時一級快取失效問題
有一點需要注意:
如果對某個SqlSession執行了commit,則會清空這個SqlSession中的一級快取,目的是為了防止髒讀,在上面的例子中,如果第一次查詢後,做了一次更新操作,然後sqlSession.commit()了,此時會清空整個SqlSession的一級快取,那麼第二次查詢時就得重新的從資料中查詢了。
以上這篇mybatis中的一級快取深入剖析就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。