mybatis缓存分一级和二级
一级缓存在配置文件中配置,分SESSION
和 STATEMENT
,默认是SESSION
缓存,
配置如下:
#开启一级缓存
<setting name="localCacheScope" value="SESSION"/>
#开启一级缓存
<setting name="localCacheScope" value="STATEMENT"/>
今天的问题是开启了<setting name="localCacheScope" value="STATEMENT"/>
后就不会有脏读,相当于关闭了一级缓存
毕竟禁用一级缓存不是很好,所以决定研究一下为啥更新之后没有清空一级缓存.
mybatis是在org.apache.ibatis.executor.BaseExecutor
执行增删改查操作的.
我们在里面打断点
@SuppressWarnings("unchecked")
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
上面代码有两处会触发 清空一级缓存, clearLocalCache();我们发现即使在
XML配置文件中加上了useCache="false"
也是无效的,因为这个是控制二级缓存的.
<select id="querySerialNoToUem" resultMap="DocAsnSubSerialNo" parameterType="DocAsnSubSerialNo" useCache="false" >
SELECT T.*
FROM DOC_ASN_SUBSERIALNO T
WHERE T.UEM_SERIALNO_FLAG = 'N'
AND ASNNO = #{asnno,jdbcType=VARCHAR}
and rownum <=500
</select>
跟踪代码观察到
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
让这个条件变成true就可以了.默认mybatis的配置flushCache="true"
就是等于true,为啥无效呢???
但是我们显式的添加上就有效了.
因为项目中我们用到了通用mapper,我们发现在通用Mapper里面 tk.mybatis.mapper.mapperhelper.MapperTemplate
类中
statementBuilder.flushCacheRequired(false);
默认都是将刷新一级缓存设置为 false了.这就是我们刚刚在
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
处 ms.isFlushCacheRequired() 为 false的原因.所以我们要显示指定一下.
网友评论