緩存機制是爲了減輕數據庫壓力,提高數據庫性能。
Mybatis查詢緩存分爲一級緩存和二級緩存,默認開啓一級緩存。
- 一級緩存是
SqlSession
級別的緩存,PerpetualCache
。 - 二級緩存是
mapper
級別的緩存。是多個SqlSession
共享的。
一、一級緩存SqlSession
級別
一級緩存是SqlSession
級別的緩存,在操作數據庫時需要構造SqlSession
對象,在對象中有一個HashMap
用於存儲緩存數據。不同的SqlSession
之間的緩存數據區域HashMap
是互不影響的。
Mybatis緩存機是基於id
進行緩存的,也就是說,Mybatis使用HashMap緩存數據時,是使用對象的id
作爲key
,而對象作爲value
保存的。
第一次以id
爲1
進行查詢執行了一條select
語句,第二次獲取id
爲1
的數據,不會再執行select
語句。
如果不執行session.commit()
,操作沒有提交到數據庫,此時Mybatis不會清空SqlSession
緩存。
若在第一次查詢id
爲的數據時執行了一條select
語句,接下來執行了一個update,delete,insert
into
操作,Mybatis爲了保證緩存中存儲的最新信息,會清空SqlSession
緩存。
因一級緩存是SqlSession
級別的,如果在執行第一次根據id
查詢後,執行了close()
方法,該方法會關閉SqlSession
緩存,第二次根據相同的id
查詢,一級緩存也就是SqlSession
緩存是一個新的對象,會再次執行select
語句。
在實際的項目開發中,往往會將Mybatis
與Spring
整合,SqlSession
會交給Spring
管理,每查詢結束後,Spring
會清空當前的SqlSession
釋放資源,也就每次查詢所使用的SqlSession
是不相同的,導致Mybatis
的一級緩存失效。
二、二級緩存mapper
級別
二級緩存是mapper
級別的緩存,是多個SqlSession
使用同一個mapper
的sql
語句去操作數據庫,得到的數據會存在二級緩存區域。
二級緩存也是使用HashMap
進行數據存儲的,範圍比一級緩存更大,是跨SqlSession
的,多個SqlSession
可以共用二級緩存。
二級緩存是多個SqlSession
共享的,其作用域是mapper
的同一個namespace
。不同的SqlSession
兩次執行相同namespace
下的sql
語句,且向sql
中傳遞的參數也相同,即最終執行相同的sql
語句,即第一次執行完畢會將從數據庫查詢到的數據寫入緩存(內存),第二次查詢會從緩存中獲取數據,不再去底層數據庫查詢,從而提高查詢效率。
當Mybatis在一級緩存中沒有找到與id
對應的對象時,就會去二級緩存中查找,如果還沒有,就去數據庫查找。
Mybatis默認沒有開啓二級緩存,需要在setting
全局參數中配置開啓二級緩存。開啓配置如下:
<settings>
<!-- 開啓二級緩存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
開始當前mapper
的namespace
下的二級緩存,xxxMapper.xml
<!-- 創建一個LRU緩存,並每隔60秒刷新,最大儲儲512個對象,返回對象是隻讀 -->
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
cache
開啓當前mapper
的namespace
下的二級緩存。該元素屬性設置如下:
flushInterval
刷新間隔,單位毫秒,默認不設置沒有刷新間隔,在調用時刷新。size
緩存數目,需要緩存的對象數目,默認值是1024。readOnly
只讀,可設置爲true
或false
。默認false
,可讀寫,返回的是緩存對象的拷貝(通過序列化),會慢些,但安全。
使用二級緩存時,與查詢結果映射的Java對象,必須實現java.io.Serializable
接口的序列化和反序列化操作。如果存在你的父類,其成員都需要實現序列化接口。
實現序列化接口是爲了對緩存數據進行序列化和反序列化操作,因爲二級緩存數據存儲介質多樣,不一定在內存,有可能是硬盤或遠程服務器。
在select
中設置useCache=false
,可以禁用當前select
語句的二級緩存,即每次查詢都會發出sql
查詢,默認是true
即開該了二級緩存則該sql
使用二級緩存。該設置通常用於每次查詢都需要最新的數據情況。