MyBatis快取機制
快取機制是為了減輕資料庫壓力,提高資料庫效能。
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
使用二級快取。該設定通常用於每次查詢都需要最新的資料情況。