Mybatis3.4.x技术内幕(二十二):Mybatis一级、二级缓存原理分析
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
Mybatis的一級緩存,指的是SqlSession級別的緩存,默認(rèn)開啟;Mybatis的二級緩存,指的是SqlSessionFactory級別的緩存,需要配置。緩存是針對select來說的。
1、一級緩存
<configuration><settings><setting name="localCacheScope" value="SESSION|STATEMENT" /></settings> </configuration>localCacheScope用于配置一級緩存的范圍,默認(rèn)值是SESSION,表示SqlSession范圍;
如果配置為STATEMENT,則表示SqlSession范圍內(nèi)的一個查詢范圍,但它并不是一個Statement實(shí)例范圍。
STATEMENT舉例:查詢Student對象發(fā)送一次sql查詢,緊接著再發(fā)一次sql查詢關(guān)聯(lián)的Teacher對象,這個完整過程稱之為一個查詢。
一級緩存默認(rèn)開啟,且沒有全局關(guān)閉的配置開關(guān)。
<select ... flushCache="false" useCache="true|false"/>flushCache:同時影響了一級、二級緩存,flushCache=true,會導(dǎo)致清空本條sql(當(dāng)前MappedStatement)的一級、二級緩存,注意是當(dāng)前的,不影響其他的MappedStatement。
useCache:配置本條MappedStatement是否使用二級緩存,useCache=true,從二級緩存中獲取,沒有獲取到,才從數(shù)據(jù)庫中獲取。
org.apache.ibatis.executor.CachingExecutor#query()方法源碼:
Cache cache = ms.getCache();if (cache != null) {// flushCache作用于二級緩存flushCacheIfRequired(ms);// useCache作用于二級緩存if (ms.isUseCache() && resultHandler == null) {ensureNoOutParams(ms, parameterObject, boundSql);@SuppressWarnings("unchecked")List<E> list = (List<E>) tcm.getObject(cache, key);if (list == null) {list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);tcm.putObject(cache, key, list); // issue #578 and #116}return list;}} return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);org.apache.ibatis.executor.BaseExecutor#query()方法源碼:
if (queryStack == 0 && ms.isFlushCacheRequired()) {// flushCache作用于一級緩存clearLocalCache(); }在執(zhí)行update、insert、delete、flushCache="true"、commit、rollback、LocalCacheScope.STATEMENT等情況下,一級緩存就都會被清空。
緩存其實(shí)基本數(shù)據(jù)結(jié)構(gòu)就是一個HashMap,緩存中是否存在緩存數(shù)據(jù),依賴key的生成策略。
org.apache.ibatis.executor.BaseExecutor.createCacheKey()源碼。
@Overridepublic CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {CacheKey cacheKey = new CacheKey();cacheKey.update(ms.getId());cacheKey.update(Integer.valueOf(rowBounds.getOffset()));cacheKey.update(Integer.valueOf(rowBounds.getLimit()));cacheKey.update(boundSql.getSql());for (int i = 0; i < parameterMappings.size(); i++) {//...cacheKey.update(value);}}if (configuration.getEnvironment() != null) {// issue #176cacheKey.update(configuration.getEnvironment().getId());}return cacheKey;}id:com.mybatis3.mappers.TeacherMapper.findTeacherById
key的生成策略:id + offset + limit + sql + param value +?environment id,這些值都相同,生成的key就相同。
2、二級緩存
<configuration><settings><setting name="cacheEnabled" value="true|false" /></settings> </configuration>cacheEnabled=true表示二級緩存可用,但是要開啟話,需要在Mapper.xml內(nèi)配置。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> if (cacheEnabled) {executor = new CachingExecutor(executor); }二級緩存通過CachingExecutor來實(shí)現(xiàn),原理是緩存里存在,就返回,沒有就調(diào)用Executor delegate到數(shù)據(jù)庫中查詢。
org.apache.ibatis.executor.CachingExecutor.query()源碼。
@Overridepublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)throws SQLException {Cache cache = ms.getCache();if (cache != null) {flushCacheIfRequired(ms);if (ms.isUseCache() && resultHandler == null) {ensureNoOutParams(ms, parameterObject, boundSql);@SuppressWarnings("unchecked")List<E> list = (List<E>) tcm.getObject(cache, key);if (list == null) {list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);tcm.putObject(cache, key, list); // issue #578 and #116}return list;}}return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}FIFO:First In First Out先進(jìn)先出隊(duì)列。
flushInterval="60000",間隔60秒清空緩存,這個間隔60秒,是被動觸發(fā)的,而不是定時器輪詢的。
size=512,表示隊(duì)列最大512個長度,大于則移除隊(duì)列最前面的元素,這里的長度指的是CacheKey的個數(shù)。
CacheKey的生成策略,和一級緩存相同,id + offset + limit + sql + param value +?environment id。
readOnly="true",表示任何獲取對象的操作,都將返回同一實(shí)例對象。如果readOnly="false",則每次返回該對象的拷貝對象,簡單說就是序列化復(fù)制一份返回。
二級緩存有一個非常重要的空間劃分策略:
namespace="com.mybatis3.mappers.TeacherMapper"
namespace="com.mybatis3.mappers.StudentMapper"
即,按照namespace劃分,同一個namespace,同一個Cache空間,不同的namespace,不同的Cache空間。
每當(dāng)執(zhí)行insert、update、delete,flushCache=true時,二級緩存都會被清空。
版權(quán)提示:文章出自開源中國社區(qū),若對文章感興趣,可關(guān)注我的開源中國社區(qū)博客(http://my.oschina.net/zudajun)。(經(jīng)過網(wǎng)絡(luò)爬蟲或轉(zhuǎn)載的文章,經(jīng)常丟失流程圖、時序圖,格式錯亂等,還是看原版的比較好)
轉(zhuǎn)載于:https://my.oschina.net/zudajun/blog/747499
總結(jié)
以上是生活随笔為你收集整理的Mybatis3.4.x技术内幕(二十二):Mybatis一级、二级缓存原理分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)js实现继承的5种方式
- 下一篇: 掌握Angular2的服务(servic