前言
mybatis 默认开启一级缓存,为什么我们很少遇到缓存带来的问题呢;我工作6年也只遇到过一次,最近才遇到的,并且我还记录了:不懂myabits缓存引发的问题这篇文章主要是记录当时排查这个问题的过程。今天这篇文主要回顾一下一级缓存的知识。
什么时候会查询缓存(同时满足)
- 相同的 namespace(同一个命名空间,即同一个 Mapper 文件),执行相同的Mapper方法
- 相同的 SQL 参数;
- 在同一个会话
SqlSession
当中;
什么时候会清空缓存
- 不能够在查询之前执行
clearCache
。 - 中间不能执行任何
update
、delete
、insert
操作(否则会将SqlSession
中的数据全部清空)。
关键代码BaseExecutor
query 代码
1.mapperStatment 可以配置是否刷新缓存
2.查询完成之后,会根据设置的缓存作用域对缓存进行处理,如果是Statement基本,就会调用clearLocalCache方法
@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 #601deferredLoads.clear();// 判断缓存范围 默认是Session会话级别if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;
}
update 代码
- 进入方法是就先执行的clearLocalCache方法
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}clearLocalCache();return doUpdate(ms, parameter);
}
有疑惑的地方,或者我有写的不对地方 欢迎大家批评指正