mybatis一級(jí)緩存和二級(jí)緩存的區(qū)別及說(shuō)明
我們通常說(shuō)mybatis中一級(jí)緩存是sqlSession級(jí)別的,二級(jí)緩存是namespace級(jí)別的,這篇筆記主要來(lái)記錄下這么說(shuō)的原理
結(jié)論
先說(shuō)結(jié)論吧,一級(jí)緩存之所以說(shuō)是sqlSession級(jí)別的,是因?yàn)橐患?jí)緩存的數(shù)據(jù)是存放在了sqlSession的一個(gè)內(nèi)部屬性中,所以,每次openSession()開(kāi)啟一個(gè)sqlSession之后,一級(jí)緩存就會(huì)失效
二級(jí)緩存之所以可以跨sqlSession,是因?yàn)槎?jí)緩存的數(shù)據(jù),是存放在mappedStatement對(duì)象中的一個(gè)內(nèi)部屬性中,這里說(shuō)的內(nèi)部屬性其實(shí)不太準(zhǔn)確,但是先忽略,后面會(huì)詳細(xì)解釋
我們知道,mybatis在啟動(dòng)的時(shí)候,會(huì)解析全局配置文件,會(huì)把mapper.xml文件中的一個(gè)個(gè)sql片段,解析成一個(gè)個(gè)mappedStatement對(duì)象,所以,這里二級(jí)緩存自然也就是namespace級(jí)別的
源碼
在mybatis源碼中,CachingExecutor是二級(jí)緩存的處理類,BaseExecutor是一級(jí)緩存的處理類

我們先來(lái)看一級(jí)緩存的處理
一級(jí)緩存

這里是一級(jí)緩存的處理,會(huì)發(fā)現(xiàn),這里是從localCache中根據(jù)key獲取value的,換而言之,這里的localCache大概率就是我們所謂的一級(jí)緩存了,我們看下localCache是在哪里賦值的

可以看到,localCache是在BaseExecutor的構(gòu)造函數(shù)中,每次new 出來(lái)的,所以,這里我們可以知道,只要new 一個(gè)BaseExecutor對(duì)象,就會(huì)有一個(gè)localCache,那對(duì)應(yīng)的一級(jí)緩存就不一樣,我們?cè)倏聪?,在正常的sql執(zhí)行過(guò)程中,BaseExecutor是在什么時(shí)候初始化的
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
org.apache.ibatis.session.Configuration#newExecutor()
這里可以看到,在通過(guò)openSession()初始化sqlSession對(duì)象的時(shí)候,就會(huì)初始化一個(gè)executor對(duì)象
所以,我們說(shuō)一級(jí)緩存是executor級(jí)別的

二級(jí)緩存
我們接著來(lái)看二級(jí)緩存的邏輯

二級(jí)緩存是從這里的tcm這個(gè)對(duì)象中來(lái)獲取的,但是實(shí)際上,我們調(diào)到tcm.getObject()方法中,會(huì)發(fā)現(xiàn)實(shí)際上是從入?yún)⒌腸ache來(lái)獲取的,所以我們需要看下這里入?yún)⒌腸ache是從哪里獲取到的
可以看到這個(gè)方法的第一行,是從MappedStatement對(duì)象中獲取到的

可以看到,mappedStatement對(duì)象是從configuration對(duì)象中獲取到,所以我們要看下configuration的mappedStatement對(duì)象是什么時(shí)候賦值的
org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement()

在這個(gè)方法中,可以看到,最終會(huì)把statement對(duì)象設(shè)置的configuration中,同時(shí)需要注意的是,我們用到的cache對(duì)象是從currentCache來(lái)的,所以我們需要關(guān)注,currentCache是從哪里來(lái)的?
在同類中,org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache
這個(gè)方法中,會(huì)給currentCache賦值

如果看過(guò)前面兩篇關(guān)于mybatis源碼解析博客的,應(yīng)該會(huì)比較清楚,這里的useNewCache()方法,就是在解析mapper.xml文件中的節(jié)點(diǎn)時(shí),調(diào)用的
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement
org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache

截圖中的這個(gè)方法是解析一個(gè)mapper.xml的邏輯

所以,我們發(fā)現(xiàn)
在解析mapper.xml文件的時(shí)候,會(huì)解析配置的節(jié)點(diǎn),在解析這個(gè)節(jié)點(diǎn)的時(shí)候,會(huì)初始化一個(gè)cache對(duì)象,這個(gè)cache對(duì)象,會(huì)賦值給currentCache然后繼續(xù)解析一個(gè)個(gè)sql片段,這一個(gè)mapper.xml文件中,無(wú)論有多少個(gè)sql,這里的currentCache都是一樣的二級(jí)緩存在使用的時(shí)候,會(huì)從mappedStatement對(duì)象中獲取currentCache,如果currentCache不為null,就表示需要使用二級(jí)緩存然后從currentCache,根據(jù)key獲取value這里需要知道的是:這里的currentCache,也是對(duì)PerpetualCache的包裝,以前文章有介紹過(guò),這次不做過(guò)多的解讀
所以,我們說(shuō)二級(jí)緩存是namespace級(jí)別的
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 一文搞懂MyBatis一級(jí)緩存和二級(jí)緩存
- Java Mybatis一級(jí)緩存和二級(jí)緩存
- MyBatis一級(jí)緩存與二級(jí)緩存原理與作用分析
- Mybatis詳細(xì)對(duì)比一級(jí)緩存與二級(jí)緩存
- Mybatis?一級(jí)緩存和二級(jí)緩存原理區(qū)別
- Mybatis的一級(jí)緩存和二級(jí)緩存原理分析與使用
- 關(guān)于mybatis的一級(jí)緩存和二級(jí)緩存的那些事兒
- Mybatis 一級(jí)緩存與二級(jí)緩存的實(shí)現(xiàn)
- MyBatis 延遲加載、一級(jí)緩存、二級(jí)緩存(詳解)
- MyBatis中一級(jí)緩存和二級(jí)緩存的區(qū)別
相關(guān)文章
springboot帶有進(jìn)度條的上傳功能完整實(shí)例
這篇文章主要介紹了springboot帶有進(jìn)度條的上傳功能,結(jié)合完整實(shí)例形式分析了springboot帶進(jìn)度條上傳的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
使用SQL保留兩位小數(shù)的實(shí)現(xiàn)方式
SQL中保留兩位小數(shù)有三種方法:1、使用ROUND()函數(shù)進(jìn)行四舍五入;2、使用CONVERT()函數(shù)和3、CAST()函數(shù)進(jìn)行強(qiáng)制類型轉(zhuǎn)換,這兩種方法會(huì)截?cái)喽嘤嗟奈粩?shù),ROUND()函數(shù)會(huì)保留0位,而CONVERT()和CAST()會(huì)刪除多余的02024-11-11
Mybatis RowBounds 限制查詢條數(shù)的實(shí)現(xiàn)代碼
Oracle 數(shù)據(jù)庫(kù)查詢?cè)黾覴owBounds限制查詢條數(shù),默認(rèn)是0到1000條。下面給大家分享Mybatis RowBounds 限制查詢條數(shù)的實(shí)現(xiàn)代碼,需要的朋友參考下吧2016-11-11
使用Java判定一個(gè)數(shù)值是否在指定的開(kāi)閉區(qū)間范圍內(nèi)
這篇文章主要給大家介紹了關(guān)于使用Java判定一個(gè)數(shù)值是否在指定的開(kāi)閉區(qū)間范圍內(nèi)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-09-09
SpringBoot文件上傳與下載功能實(shí)現(xiàn)詳解
文件上傳與下載是Web應(yīng)用開(kāi)發(fā)中常用的功能之一。接下來(lái)我們將討論如何在Spring?Boot的Web應(yīng)用開(kāi)發(fā)中,如何實(shí)現(xiàn)文件的上傳與下載,感興趣的可以了解一下2022-10-10
解析電子郵件的基本概念及JavaMail API郵件功能使用
這篇文章主要介紹了電子郵件的基本概念及JavaMail API郵件功能使用,包括用Java來(lái)發(fā)送郵件的示例,需要的朋友可以參考下2016-02-02

