今天想挑战一下一级缓存。
直接从github上下载了源码。https://github.com/mybatis/mybatis-3.git
既然一级缓存是SqlSession级的,就从SqlSession开始看吧。SqlSession是个接口,实现是DefaultSqlSession,据说SqlSessionManager还没有使用。
这里更新一下理解,说一级缓存是SqlSession级的,并不是说直接在SqlSession对象上,而是在BaseExecutor中才有的localCache。由PerpetualCache类封装。而我们创建一个SqlSession的时候肯定会创建一个Executor。也就是说这个一级缓存是SqlSession级的。
试着从selectOne(String statment) 开始吧。比想象中要容易。
@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; //先从localCache中获取 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; }
从DefaultSqlSession来看,有一个Executor属性,Excutor又一个属性就是 localCache,实际的数据结构就是一个map。
再看一下当执行过一次查询的时候这个cache
难道这localCache是不能被关闭的吗!
网上查了一下 发现一篇写的不错的blog https://blog.youkuaiyun.com/j7636579/article/details/73647885
看来DefaultSqlsession的BaseExecutor 起码是不能关闭的,真要关闭还真要费一番周折。
原来以为setting中的缓存开关是一级缓存呢!错错错!
<!-- 开启延迟加载 -->
<settings>
<!-- lazyLoadingEnabled:延迟加载启动,默认是false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- aggressiveLazyLoading:积极的懒加载,false的话按需加载,默认是true -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存,默认是false -->
<setting name="cacheEnabled" value="true"/>
</settings>
这里cacheEnabled是全局的二级缓存。学习了,学习了。各个mapper上可以单独去设置当前mapper是否开启。
mybatis的一级缓存,默认情况下都处于开启状态,只能使用自带的PerpetualCache,无法配置第三方缓存
稍后再去研究一下二级缓存。
学习一下:
https://tech.meituan.com/mybatis_cache.html