mybatis是一個查詢資料庫的封裝框架,主要是封裝提供靈活的增刪改sql,開發中,service層能夠通過mybatis組件查詢和修改資料庫中表的數據;作為查詢工具,mybatis有使用緩存,這裡講一下mybatis的緩存相關源碼。
緩存
在計算機裡面,任何信息都有源頭,緩存一般指源頭信息讀取後,放在內存或者其他讀取較快的地方,下次讀取相同信息不去源頭查詢而是直接從內存(或者能快速存取的硬體)讀取。這樣可以減少硬體使用,提高讀取速度。
mybatis也是這樣,查詢資料庫的數據之後,mybatis可以把查詢結果緩存到內存,下次查詢如果查詢語句相同,並且查詢相關的表的數據沒被修改過,就可以直接返回緩存中的結果,而不用去查詢資料庫的語句,有效節省了時間。
關於mybatis中一級和二級緩存命名疑問
緩存概念較用於CPU讀取數據,有一級和二級緩存,讀取順序是先一級緩存,再二級緩存。
按照這個概念,通過源碼了解mybatis的Mapper中的緩存是一級緩存,SqlSession的中緩存是二級緩存。看到一些介紹mybatis緩存的相關文章命名反過來的,稱SqlSession中的緩存稱為一級緩存,對此有疑惑……
簡單看一下mybatis緩存相關源碼
Mapper中的緩存(一級)
mapper中的緩存,默認配置是開啟,但需要在映射文件mapper.xml中添加<cache/>標籤
配置false可以關閉mapper中的緩存
mapper緩存的解析
org.apache.ibatis.builder.xml.XMLMapperBuilder
org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache():
在映射文件mapper中如果沒有cache標籤,解析時不會執行上面的useNewCache方法,cache為null,就不會使用mapper緩存(相當於失效)。
查詢使用mapper緩存邏輯
org.apache.ibatis.executor.CachingExecutor :
上面代碼中ms對象(MappedStatement )是在系統啟動時創建的對象,cache也是,不與SqlSession綁定,所以SqlSession不同,mapper緩存依然可以使用,這區別於SqlSession中的緩存。
SqlSession中的緩存(二級)
通過查看源碼可知,SqlSsession中是有緩存的,所以每次(新請求)會話SqlSession不同,緩存是空的;相同的SqlSession中的緩存才有效。
mybatis默認Sqlsession:org.apache.ibatis.session.defaults.DefaultSqlSession
構造方法中傳入executor(查詢執行對象)
executor中攜帶二級緩存成員變量:
查詢使用SqlSession緩存邏輯
org.apache.ibatis.executor.BaseExecutor.query()
二級緩存和一級緩存不用想,資料庫的數據被修改時要清空緩存,不然數據有誤;至於怎麼清空,是另一套邏輯,mapper中的cache標籤可以配置一些參數,比如緩存定期清空。
一級二級緩存先後順序
從概念上來將,先讀取的就是一級緩存,後讀取是二級緩存
通過源碼可以知道這裡使用了類似裝飾者模式的設計,在創建Executor的時候,邏輯如下
所以當開啟緩存的時候,查詢邏輯從CachingExecutor.query開始
在SqlSession查詢數據的時候,按照代碼邏輯:
1 CachingExecutor.query 中嘗試讀取mapper中的緩存(一級)
org.apache.ibatis.executor.CachingExecutor.query()
2 BaseExecutor.query 中嘗試讀取SqlSession中的緩存(二級)
org.apache.ibatis.executor.BaseExecutor.query()
最後一級二級緩存都沒有,就查詢資料庫