标签:
~
缓存是提供应用系统性能的重要手段,前面已经介绍过Mybatis是一级缓存,与一级缓存不同的是,二级缓存的作用范围扩大到了应用级别,并且可以比一级缓存更细粒度的对二级缓存的应用进行配置。下面就详细叙述一下Mybatis的二级缓存实现。
二级缓存的工作流程
不多说,先上图,图解是攻城狮最好的朋友^_^…
前面在叙述一级缓存的时候已经说过,一级缓存是一块放在Executor中的map内存块。试想一下,如果二级缓存也是Executor中的内存块可以可以呢?…… 当然不可以!为啥?因为二级缓存要支持细粒度的配置,并且是否应用二级缓存也是用户说了算。
二级缓存的工作流程是这样的:
开启一个回话时,mybatis会检查在核心配置文件中是否配置<setting name="cacheEnabled" value="true"/>
,如果配置,则Mybatis在创建对象时,会创建一个CachingExecutor,该类是Executor的包装类,mybatis利用装饰设计模式对Exector进行了缓存支持的增强。
public <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, key, parameterObject, boundSql);
if (!dirty) {
cache.getReadWriteLock().readLock().lock();
try {
@SuppressWarnings("unchecked")
List<E> cachedList = (List<E>) cache.getObject(key);
if (cachedList != null) return cachedList;
} finally {
cache.getReadWriteLock().readLock().unlock();
}
}
List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
return list;
}
}
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
以上代码是CachingExecutor中的片段,可以很容易看出,在执行查询时,先检查了cache。如果二级缓存中没有想要的数据,则会从数据库查询,得到结果后放到缓存中,然后在将结果返回给用户。
<setting name="cacheEnable" value="true">
,这是二级缓存的全局开关。 <setting name="cacheEnabled" value="true"/>
2)在sqlMapper配置文件中配置<cache/>
,该标签用于将二级缓存的控制权交到每个mapper手里,同时,利用该标签还可以配置诸如回收策略、刷新频率,缓存大小,缓存类型等。
<cache
eviction = "FIFO"
flushInterval = "60000"
size="512"
readOnly="true"
type="org.mybatis.caches.ehcache.EhcacheCache"/>
3)在<select/>
标签中应用useCache属性userCache=true
,来进一步说明这个查询需要用到二级缓存,
<select id="secondLevelCache" resultType="Pet" useCache="true">
select <include refid="column"/> from pet where owner = ‘zhangsan‘
</select>
一级缓存与二级缓存的使用顺序
从上面的图中,其实我们就可以看出mybatis在应用缓存时具体策略,首先会先从二级缓存查询数据(这个那个CachingExecutor的第一道关卡),如果没找到,则把寻找数据的人员交给被CachingExecutor装饰的BaseExecutor,BaseExecutor首先会查询当前会话的一级缓存(当然多数情况下是徒劳,二级缓存中都没有,一级缓存中怎么可能有呢),若没有找到数据,最终与数据库建立连接,得到数据,放入一级缓存,放入二级缓存,最后返回给用户。
综上所述:
1)二级缓存
2)一级缓存
3)查询数据库
二级缓存的回收策略
LRU – 最近最少使用的:移除最长时间不被使用的对象
FIFO – 先进先出:按对象进入缓存的顺序来移除它们
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u012302681/article/details/47653035