老司機學習MyBatis之一級快取原理以及失效情況
一、前言
MyBatis將資料快取設計成兩級結構,分為一級快取、二級快取:
一級快取是Session會話級別的快取,位於表示一次資料庫會話的SqlSession物件之中,又被稱之為本地快取。一級快取是MyBatis內部實現的一個特性,使用者不能配置,預設情況下自動支援的快取,使用者沒有定製它的權利(不過這也不是絕對的,可以通過開發外掛對它進行修改);
每當我們使用MyBatis開啟一次和資料庫的會話,MyBatis會創建出一個SqlSession物件表示一次資料庫會話。在對資料庫的一次會話中,我們有可能會反覆地執行完全相同的查詢語句,如果不採取一些措施的話,每一次查詢都會查詢一次資料庫,而我們在極短的時間內做了完全相同的查詢,那麼它們的結果極有可能完全相同,由於查詢一次資料庫的代價很大,這有可能造成很大的資源浪費。
為了解決這一問題,減少資源的浪費,MyBatis會在表示會話的SqlSession物件中建立一個簡單的快取,將每次查詢到的結果結果快取起來,當下次查詢的時候,如果判斷先前有個完全一樣的查詢,會直接從快取中直接將結果取出,返回給使用者,不需要再進行一次資料庫查詢了。
如下圖所示,MyBatis會在一次會話的表示—-一個SqlSession物件中建立一個本地快取(local cache),對於每一次查詢,都會嘗試根據查詢的條件去本地快取中查詢是否在快取中,如果在快取中,就直接從快取中取出,然後返回給使用者;否則,從資料庫讀取資料,將查詢結果存入快取並返回給使用者。
這一節,我們將簡單的說說什麼是一級快取以及什麼情況下會導致一級快取失效?
二、案例
建立一個新的Maven工程MyBatisPrimaryCache,工程結構目錄如下
在測試類MyBatis中增加測試方法testPrimaryCache
列印檢視一下控制檯
2017-08-17 21:08:20,836 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:08:20,888 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:08:20,924 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
true
從控制檯我們可以看到,即便Java程式碼中查詢Emp資訊,寫了兩段程式碼,但是實際上去後臺數據庫查詢只做了一次SQL呼叫,第二次查詢並沒有去資料庫查詢,第二次獲取的資料與第一次一樣,它就直接從快取中拿了資料。
如上我們簡單的體驗了一下一級快取的存在
一級快取我們也稱作SqlSession級別的快取,一級快取預設就是開啟的。既然是SqlSession級別的快取,那就說明每個SqlSession物件擁有自己的一份資料,每個SqlSession之間是不能共享快取的。但是每個獨立的SqlSession快取也有失效的時候。
下面我們通過案例看看哪些情況會導致一級快取失效
①SqlSession不同
上面第一個測試案例,我們查詢emp01和emp02都是使用的同一個mapper物件,如果mpper不是同一個會是什麼情況,修改程式碼如下:
測試列印,檢視一下控制檯
2017-08-17 21:28:41,663 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:28:41,731 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:28:41,774 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
2017-08-17 21:28:41,786 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:28:41,787 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:28:41,789 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
false
如上,我們發現控制檯列印了兩段SQL,第二次查詢取資料庫重新獲取了資料,封裝成了一個新的物件,emp01==emp02 為false,說明不是同一個物件。一級快取失效。
②SqlSession相同,但是查詢條件不一樣(當前一級快取中還沒有資料)
必然上面查詢會發出兩條SQL,查詢2號員工時,因為本來就是第一次查詢,所以不可能存在於快取中的資料,需要呼叫資料庫查詢資料。
③SqlSession相同,兩次查詢之間增加了增刪改操作
測試列印,檢視一下控制檯如下:
2017-08-17 21:45:12,885 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:45:12,960 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:45:13,000 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
2017-08-17 21:45:13,052 [main] [com.queen.mybatis.mapper.EmpMapper.updateEmp]-[DEBUG] ==> Preparing: update t_emp SET emp_name=?, emp_email=? where id=?
2017-08-17 21:45:13,053 [main] [com.queen.mybatis.mapper.EmpMapper.updateEmp]-[DEBUG] ==> Parameters: tom123(String), [email protected](String), 3(Integer)
2017-08-17 21:45:13,053 [main] [com.queen.mybatis.mapper.EmpMapper.updateEmp]-[DEBUG] <== Updates: 1
=====資料修改成功!======
2017-08-17 21:45:13,054 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:45:13,054 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:45:13,056 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
false
如上所述,一級快取失效了,雖然兩次都是查詢的同一條資料,但是卻發了兩次SQL,封裝了兩次物件且不是同一個物件。所以這種情況也會導致快取失效。這種情況也比較容易理解,因為你在做修改的時候,可能就會修改到這條資料,當你修改了這條資料後,難道我還要去快取中拿資料嗎?當然是不行的。只要資料庫有變化,就要再次去資料庫查詢資料。
④SqlSession相同,但是我們手動清除了一級快取(快取清空)
測試列印,檢視一下控制檯如下:
2017-08-17 21:56:21,619 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:56:21,680 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:56:21,723 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
2017-08-17 21:56:21,724 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id = ?
2017-08-17 21:56:21,724 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] ==> Parameters: 1(Integer)
2017-08-17 21:56:21,726 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpById]-[DEBUG] <== Total: 1
Emp [id=1, empName=queen3aasd21, [email protected], deptId=1]
false
我們發現這個時候也一樣,快取也失效了,第二次查詢還是去資料庫重新查詢了一遍資料。因為快取中已經沒有資料了。
=======歡迎大家拍磚,小手一抖,多多點贊喲!=======
相關推薦
老司機學習MyBatis之一級快取原理以及失效情況
一、前言MyBatis將資料快取設計成兩級結構,分為一級快取、二級快取:一級快取是Session會話級別的快取,位於表示一次資料庫會話的SqlSession物件之中,又被稱之為本地快取。一級快取是MyBatis內部實現的一個特性,使用者不能配置,預設情況下自動支援的快取,使用
老司機學習MyBatis之動態SQL使用trim自定義字串擷取
一、前言前面一個章節講到,如果where標籤裡面,and或者or寫在後面,最後字串拼串後,如果最後一個條件沒有加上,可能會出現SQL多出 and或者or 的情形。那我們是不是沒有辦法解決這種問題的產生,事實上MyBatis為我們提供了另外一種標籤trim,可以簡單粗暴的解決這
老司機學習MyBatis之MyBatis如何使用Map處理引數
一、前言如果多個引數不是業務模型中的資料,沒有對應的POJO,為了方便,我們直接封裝成Map傳入。#{key}取出map中對應的值。二、案例在UserMapper.java增加查詢方法findUserB
老司機學習MyBatis之如何使用typeAliases別名和@Alias註解
一、前言typeAliases是MyBatis中的別名處理器類,翻譯過來就是別名的意思。別名處理器的作用就是把Java型別,給它起一個簡單一點的別名,這樣我們在XML檔案中引入全類名的地方就可以使用別名
Mybatis之一級快取和二級快取
Mybatis的快取 Mybatis的快取,包括一級快取和二級快取 一級快取是預設使用的。 二級快取需要手動開啟。 一級快取 一級快取指的就是sqlsession,在sqlsession中有一個數據區域,是map結構,這個區域就是一級快取區域。一級快取中的key
mybatis查詢快取之一級快取
什麼是查詢快取? 快取是介於應用程式和物理資料來源之間 mybatis提供查詢快取,用於減輕資料壓力,提高資料庫效能。 mybaits提供一級快取,和二級快取。 一級快取是sqlSession級別的快取。在操作資料庫時需要構造sqlSession物件,在物件中有一個數據結構(Has
MyBatis快取之一級快取
1 快取物件 不跨session: package com.rl.test; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.ses
《深入理解mybatis原理(三)》 MyBatis的一級快取實現詳解 及使用注意事項
0.寫在前面 MyBatis是一個簡單,小巧但功能非常強大的ORM開源框架,它的功能強大也體現在它的快取機制上。MyBatis提供了一級快取、二級快取 這兩個快取機制,能夠很好地處理和維護快取,以提高系統的效能。本文的目的則是向讀者詳細介紹MyBatis的一級快取,深入原始碼,解析MyBa
hibernat之一級快取的原理
Po物件 Po物件的三種狀態以及相互轉化的結果 Po物件處於瞬時(臨時)狀態和脫管狀態的時候,都不能直接於資料庫互動 只有物件處於持久化狀態的時候,才能被儲存到資料庫 通俗的解釋三種狀態: 瞬時態:通過new出來的物件,如果是自然主鍵,則必須指定主鍵。如果是代理主鍵(主鍵
mybatis快取之一級快取(一)
> 對於mybatis框架。彷彿工作中一直是在copy著使用。對於mybatis快取。並沒有一個準確的認知。趁著假期。學習下mybatis的快取。這篇主要學習mybatis的一級快取。 ## 為什麼使用快取 ![](https://img2020.cnblogs.com/blog/891580/20200
mybatis快取之一級快取(二)
這篇文章介紹下mybatis的一級快取的生命週期 ## 一級快取的產生 一級快取的產生,並不是看mappper的xml檔案的select方法,看下面的例子 mapper.xml ``` ``` test ``` @Test public void testSelectAsU
Python學習筆記之裝飾器原理
開放 直接 蘋果 def 復用 學習 clas bsp pytho 1 def decorator(fn): 2 def wrapper(): 3 print("詢價") 4 fn() 5 print("購
Mybatis的一級快取和二級快取詳解
注:本筆記是根據尚矽谷的MyBatis視訊記錄的 對於任何一個持久層框架,都有快取機制;快取在電腦中有一塊真實的儲存空間(https://baike.baidu.com/item/%E7%BC%93%E5%AD%98/100710?fr=aladdin); 兩個關於mybatis快取額外的連
Mybatis的一級快取和二級快取執行順序
1、先判斷二級快取是否開啟,如果沒開啟,再判斷一級快取是否開啟,如果沒開啟,直接查資料庫 2、如果一級快取關閉,即使二級快取開啟也沒有資料,因為二級快取的資料從一級快取獲取 3、一般不會關閉一級快取 4、二級快取預設不開啟 5、如果二級快取關閉,直接判斷一級快取是否有資料,如果沒有就
Hibernate之一級快取和二級快取
1:Hibernate的一級快取: 1.1:使用一級快取的目的是為了減少對資料庫的訪問次數,從而提升hibernate的執行效率;(當執行一次查詢操作的時候,執行第二次查詢操作,先檢查快取中是否有資料,如果有資料就不查詢資料庫,直接從快取中獲取資料); 1.
Mybatis之二級快取
Mybatis預設對二級快取是關閉的,一級快取預設開啟; 下面就說說為什麼使用二級快取需要注意: 二級快取是建立在同一個namespace下的,如果對錶的操作查詢可能有多個namespace,那麼得到的資料就是錯誤的。 舉個簡單的例子,訂單和訂單詳情,o
Mybatis之攔截器原理(jdk動態代理優化版本)
在介紹Mybatis攔截器程式碼之前,我們先研究下jdk自帶的動態代理及優化 其實動態代理也是一種設計模式...優於靜態代理,同時動態代理我知道的有兩種,一種是面向介面的jdk的代理,第二種是基於第三方的非面向介面的cglib. 我們現在說的是jdk的動態代理,因為mybatis攔截器也是基於這個實現的。
MyBatis 的一級快取實現詳解及使用注意事項
轉自:https://blog.csdn.net/chenyao1994/article/details/79233725 0.寫在前面 MyBatis是一個簡單,小巧但功能非常強大的ORM開源框架,它的功能強大也體現在它的快取機制上。MyBatis提供了一級快取、二級快取 這兩個快取機制,
學習Mybatis(3):快取
Mybatis預設只開啟了一級快取(SqlSession級),沒有開啟二級快取(SqlSessionFactory級),需要開啟的話,可以在Mapper檔案中寫上 <cache/> 快取開啟後: 1.需要使用SqlSession::commit()方法才會提交操作 2.如
Mybatis的一級快取和二級快取的理解和區別
一級快取基於sqlSession預設開啟,在操作資料庫時需要構造SqlSession物件,在物件中有一個HashMap用於儲存快取資料。不同的SqlSession之間的快取資料區域是互相不影響的。一級快取的作用域是SqlSession範圍的,當在同一個sqlSession中執