mybatis 一級快取和二級快取 配置使用
mybatis提供查詢快取,用於減輕資料壓力,提高資料庫效能。
mybaits提供一級快取,和二級快取。
1、一級快取
MyBatis 預設開啟了一級快取,一級快取是在SqlSession 層面進行快取的。即,同一個SqlSession ,多次呼叫同一個Mapper和同一個方法的同一個引數,只會進行一次資料庫查詢,然後把資料快取到緩衝中,以後直接先從快取中取出資料,不會直接去查資料庫。
但是不同的SqlSession物件,因為不用的SqlSession都是相互隔離的,所以相同的Mapper、引數和方法,他還是會再次傳送到SQL到資料庫去執行,返回結果。
同一個sqlsession裡面存在,快取用map儲存:
key:sqlsession.hashcode+statementId+sql value:查詢出來的物件。
一級快取:
第一次發起查詢使用者id為1的使用者資訊,先去找快取中是否有id為1的使用者資訊,如果沒有,從資料庫查詢使用者資訊。
得到使用者資訊,將使用者資訊儲存到一級快取中。
如果sqlSession去執行commit操作(執行插入、更新、刪除),清空SqlSession中的一級快取,這樣做的目的為了讓快取中儲存的是最新的資訊,避免髒讀。
第二次發起查詢使用者id為1的使用者資訊,先去找快取中是否有id為1的使用者資訊,快取中有,直接從快取中獲取使用者資訊。
一級快取的應用:
正式開發,是將mybatis和spring進行整合開發,事務控制在service中。
一個service方法中包括 很多mapper方法呼叫。
service{
//開始執行時,開啟事務,建立SqlSession物件
//第一次呼叫mapper的方法findUserById(1)
//第二次呼叫mapper的方法findUserById(1),從一級快取中取資料
//方法結束,sqlSession關閉
}
如果是執行兩次service呼叫查詢相同 的使用者資訊,不走一級快取,因為session方法結束,sqlSession就關閉,一級快取就清空
禁用一級快取:
1、每次傳入不同的sql,加一個隨機串到SQL裡面 where #{randomString}=#{randomString}。其實之前快取資料並未清除,只是在快取資料中未找到相同sql,才從資料庫查詢資料。
2、呼叫SqlSession.clearCache(),問題解決。
2、二級快取
二級快取是mapper級別的快取,多個SqlSession去操作同一個Mapper的sql語句,多個SqlSession可以共用二級快取,二級快取是跨SqlSession的。
sqlSession1去查詢使用者id為1的使用者資訊,查詢到使用者資訊會將查詢資料儲存到二級快取中。
如果SqlSession3去執行相同 mapper下sql,執行commit提交,清空該 mapper下的二級快取區域的資料。
sqlSession2去查詢使用者id為1的使用者資訊,去快取中找是否存在資料,如果存在直接從快取中取出資料。
二級快取與一級快取區別,二級快取的範圍更大,多個sqlSession可以共享一個UserMapper的二級快取區域。
UserMapper有一個二級快取區域(按namespace分) ,其它mapper也有自己的二級快取區域(按namespace分)。
每一個namespace的mapper都有一個二快取區域,兩個mapper的namespace如果相同,這兩個mapper執行sql查詢到資料將存在相同 的二級快取區域中。
開啟二級快取:
1、在mybatis-config.xml 中配置二級快取的總開關 <setting name="cacheEnabled" value="true"/>
2、在mapper.xml 中開啟二級快取
mapper中加入<cache/>
如果這樣配置的話,很多其他的配置就會被預設進行,如:
- 對映檔案所有的select 語句會被快取
- 對映檔案的所有的insert、update和delete語句會重新整理快取
- 快取會使用預設的Least Recently Used(LRU,最近最少使用原則)的演算法來回收快取空間
- 根據時間表,比如No Flush Interval,(CNFI,沒有重新整理間隔),快取不會以任何時間順序來重新整理
- 快取會儲存列表集合或物件(無論查詢方法返回什麼)的1024個引用
- 快取會被視為是read/write(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以很安全的被呼叫者修改,不干擾其他呼叫者或縣城所作的潛在修改
可以在開啟二級快取時候,手動配置一些屬性
<cache eviction="LRU" flushInterval="100000" size="1024" readOnly="true"/>
各個屬性意義如下:
- eviction:快取回收策略 - 【預設】LRU:最少使用原則,移除最長時間不使用的物件 - FIFO:先進先出原則,按照物件進入快取順序進行回收 - SOFT:軟引用,移除基於垃圾回收器狀態和軟引用規則的物件 - WEAK:弱引用,更積極的移除移除基於垃圾回收器狀態和弱引用規則的物件
- flushInterval:重新整理時間間隔,單位為毫秒,這裡配置的100毫秒。如果不配置,那麼只有在進行資料庫修改操作才會被動重新整理快取區
- size:引用額數目,代表快取最多可以儲存的物件個數,預設值是1024
- readOnly:是否只讀,如果為true,則所有相同的sql語句返回的是同一個物件(有助於提高效能,但併發操作同一條資料時,可能不安全)。如果設定為false,則相同的sql,後面訪問的是cache的clone副本,這會慢一些,但是安全,因此預設是false。
可以在Mapper的具體方法下設定對二級快取的訪問意願:
-
useCache配置
如果一條語句每次都需要最新的資料,就意味著每次都需要從資料庫中查詢資料,可以把這個屬性設定為false,如:
<select id="selectAll" resultMap="BaseResultMap" useCache="false">
-
重新整理快取(就是清空快取)
二級快取預設會在insert、update、delete操作後重新整理快取,可以手動配置不更新快取,如下:
<update id="updateById" parameterType="User" flushCache="false" />