1. 程式人生 > >mybatis 一級快取和二級快取 配置使用

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" />