mybatis緩存的設計
繼續用提問的方式來看Mybatis的緩存設計。
1、Mybatis如何開啟緩存
Mybatis對查詢結果進行緩存,所以緩存的對象為具體的Statement
通過在Statement上是否使用緩存來啟用。
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap" fetchSize="5" statementType="PREPARED" useCache="true" >
useCache默認值為true
2、誰持有緩存?
Mybatis中有兩個對象持有緩存。
CachingExecutor以及BaseExecutor
CachingExecutor和SimpleExecutor的關系是持有的關系
public class CachingExecutor implements Executor { private final Executor delegate; private final TransactionalCacheManager tcm = new TransactionalCacheManager();
3、緩存何時開啟?
當開啟Mapper級別的緩存時,緩存被開啟
緩存是一直開啟的
4、緩存何時被命中?
5、緩存清空的時機
①數據庫發生變更(update,insert,delete),即使事物沒有提交,緩存也
②對於相同命名空間Mapper的緩存,多個線程,並發使用相同Mapper的不同語句,任意一個執行事物提交,可導致緩存失效
實際效果:
緩存 會和Mysql的rr隔離級別一致,不會導致幻讀(read uncommited)
緩存 在不使用緩存的時候,有效
驗證緩存
使用代碼驗證:
兩次查詢,只訪問了數據庫1次.第二次不再請求數據庫
一次查詢,一次更新(不提交),一次查詢.緩存失效,出發了兩次數據庫查詢。
緩存的驗證
不配置緩存時,驗證不同的sqlSesiion緩存是否通用
觸發2次數據庫訪問
配置緩存參數
<settings> <setting name="cacheEnabled" value="true"/> </settings>
<cache/>
結果出乎意料,緩存竟然沒有命中。分析下原因:
即使打開了緩存,首先也是保存在事物級別的緩存裏,TransactionalCache裏.
只有當實物提交時,才會真正將緩存轉移到delegate中(delegate是真正的Mapper之間公用的緩存)
調整代碼,後緩存生效。
讓人不理解的,出於什麽目的,要commit後,再共享?
如果在某一秒,有10個並發共同訪問數據庫。那他們會同時產生10個連接,並不會命中。
6、Mybatis緩存設計的目的
簡單,不配置也可以使用。用與在一個sqlSession中多次使用相同條件多次查詢。
7、Mybatis緩存設計的目的
增強版,也支持事物級別的緩存,同時支持不同sqlSession之間的共享。擴大可緩存的可用性。
mybatis緩存的設計