通過源碼分析MyBatis的緩存
看了通過源碼分析MyBatis的緩存這篇文章後,自己跟著源碼過了一遍,對mybatis的一級緩存和二級緩存有了更清楚的認識。
一級緩存是SqlSession級別的,同一個sqlSession在第二次執行一個相同參數的select語句並且第一次執行後沒有對數據進行更新,就會直接從緩存取值,而不再進行查找。通過閱讀源碼了解了這個過程,首先org.apache.ibatis.session.defaults.DefaultSqlSession.select(String, Object, RowBounds, ResultHandler)方法會調用executor.query(ms, wrapCollection(parameter), rowBounds, handler),然後分析executor的類型,在org.apache.ibatis.session.defaults.DefaultSqlSessionFactory類中,openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean)方法的Executor executor = configuration.newExecutor(tx, execType) 語句實例化executor,代碼如下,在SqlMapConfig.xml中cacheEnabled默認為true,即一級緩存默認開啟,故executor為CachingExecutor類型。
/* */ public Executor newExecutor(Transaction transaction, ExecutorType executorType) { /* 540 */ executorType = executorType == null ? defaultExecutorType : executorType; /* 541 */ executorType = executorType == null ? ExecutorType.SIMPLE : executorType; /* */ Executor executor; /* 543*/ if (ExecutorType.BATCH == executorType) { /* 544 */ executor = new BatchExecutor(this, transaction); } else { Executor executor; /* 545 */ if (ExecutorType.REUSE == executorType) { /* 546 */ executor = new ReuseExecutor(this, transaction); /* */ } else /* 548 */ executor = newSimpleExecutor(this, transaction); /* */ } /* 550 */ if (cacheEnabled) { /* 551 */ executor = new CachingExecutor(executor); /* */ } /* 553 */ Executor executor = (Executor)interceptorChain.pluginAll(executor); /* 554 */ return executor; /* */ } /* */
在org.apache.ibatis.executor.CachingExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql)方法中首先獲取二級緩存,由於二級緩存為空,執行該語句
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
delegate對象為org.apache.ibatis.executor.SimpleExecutor類型,繼承自org.apache.ibatis.executor.BaseExecutor類,query方法如下
BaseExecutor的屬性localCache是個PerpetualCache類型的實例,PerpetualCache類是實現了MyBatis的Cache緩存接口的實現類之一,內部有個Map<object, object>類型的屬性用來存儲緩存數據。 這個localCache的類型在BaseExecutor內部是寫死的。 這個localCache就是一級緩存!
在數據更改時會清空緩存。
二級緩存是基於namespace的,必須在sqlSession提交或關閉才會生效。需要在mapper配置文件加上<cache />。
通過源碼分析MyBatis的緩存