CachingExecutor的query()方法
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
//获得该MappedStatement的cache
Cache cache = ms.getCache();
//如果缓存不为空
if (cache != null) {
//看是否需要清除cache(在xml中可以配置flushCache属性决定何时清空cache)
this.flushCacheIfRequired(ms);
//若开启了cache且resultHandler 为空
if (ms.isUseCache() && resultHandler == null) {
this.ensureNoOutParams(ms, parameterObject, boundSql);
//从TransactionalCacheManager中取cache
List list = (List)this.tcm.getObject(cache, key);
//若取出来list是空的
if (list == null) {
//查询数据库
list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
//将结果存入cache中
this.tcm.putObject(cache, key, list);
}
return list;
}
}
//如果缓存为空,去查询数据库
return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
TransactionalCacheManager内部有一个map属性
private final Map transactionalCaches = new HashMap();
个人理解:TransactionalCacheManager作为暂存区管理器(事务缓存管理器),在没有经过commit的情况下,修改的数据会暂时存放在这里,这时查询缓存直接查缓存区,是查不到未提交的数据的.当commit后,会将暂存区的数据推送到缓存区中,这时再查询是可以查询的到的.
TransactionalCacheManager暂存区管理器内管理了很多个暂存区,每个暂存区对应相应的缓存区,putObject()方法
public void putObject(Cache cache, CacheKey key, Object value) {
this.getTransactionalCache(cache).putObject(key, value);
}
第一个参数就是暂存区的对应关系,找对应的暂存区去修改缓存区.所以所有修改缓存区第一步都是修改暂存区的数据,只有commit方法才是把数据推送到缓存区去
要跨线程使用,要保证线程安全
与会话session一致,
备注:图片由鲁班大叔视频截屏得到的