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

我們先來看一級緩存的處理
一級緩存

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

可以看到,localCache是在BaseExecutor的構造函數(shù)中,每次new 出來的,所以,這里我們可以知道,只要new 一個BaseExecutor對象,就會有一個localCache,那對應的一級緩存就不一樣,我們再看下,在正常的sql執(zhí)行過程中,BaseExecutor是在什么時候初始化的
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
org.apache.ibatis.session.Configuration#newExecutor()
這里可以看到,在通過openSession()初始化sqlSession對象的時候,就會初始化一個executor對象
所以,我們說一級緩存是executor級別的

二級緩存
我們接著來看二級緩存的邏輯

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

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

在這個方法中,可以看到,最終會把statement對象設置的configuration中,同時需要注意的是,我們用到的cache對象是從currentCache來的,所以我們需要關注,currentCache是從哪里來的?
在同類中,org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache
這個方法中,會給currentCache賦值

如果看過前面兩篇關于mybatis源碼解析博客的,應該會比較清楚,這里的useNewCache()方法,就是在解析mapper.xml文件中的節(jié)點時,調用的
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement
org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache

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

所以,我們發(fā)現(xiàn)
在解析mapper.xml文件的時候,會解析配置的節(jié)點,在解析這個節(jié)點的時候,會初始化一個cache對象,這個cache對象,會賦值給currentCache然后繼續(xù)解析一個個sql片段,這一個mapper.xml文件中,無論有多少個sql,這里的currentCache都是一樣的二級緩存在使用的時候,會從mappedStatement對象中獲取currentCache,如果currentCache不為null,就表示需要使用二級緩存然后從currentCache,根據(jù)key獲取value這里需要知道的是:這里的currentCache,也是對PerpetualCache的包裝,以前文章有介紹過,這次不做過多的解讀
所以,我們說二級緩存是namespace級別的
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot Mybatis動態(tài)數(shù)據(jù)源切換方案實現(xiàn)過程
這篇文章主要介紹了SpringBoot+Mybatis實現(xiàn)動態(tài)數(shù)據(jù)源切換方案過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04
Java導出excel時合并同一列中相同內(nèi)容的行思路詳解
這篇文章主要介紹了Java導出excel時合并同一列中相同內(nèi)容的行,需要的朋友可以參考下2018-06-06
關于SpringMVC的數(shù)據(jù)綁定@InitBinder注解的使用
這篇文章主要介紹了關于SpringMVC的數(shù)據(jù)綁定@InitBinder注解的使用,在SpringMVC中,數(shù)據(jù)綁定的工作是由 DataBinder 類完成的,DataBinder可以將HTTP請求中的數(shù)據(jù)綁定到Java對象中,需要的朋友可以參考下2023-07-07
Java中通過三級緩存解決Spring循環(huán)依賴詳解
這篇文章主要介紹了Java中通過三級緩存解決Spring循環(huán)依賴詳解,當出現(xiàn)兩個或多個 Bean 在初始化時相互依賴的情況時,Spring Boot 會將其中一個 Bean 提前暴露出來,以便其他 Bean 能夠在初始化時正確地引用它,這一策略能有效避免循環(huán)依賴導致的問題,需要的朋友可以參考下2023-09-09
Java Synchronize下的volatile關鍵字詳解
這篇文章主要介紹了Java Synchronize下的volatile關鍵字詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03

