本文共 2104 字,大约阅读时间需要 7 分钟。
今天想挑战一下一级缓存。
直接从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")@OverridepublicList 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 list; try { queryStack++; list = resultHandler == null ? (List ) 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.csdn.net/j7636579/article/details/73647885
看来DefaultSqlsession的BaseExecutor 起码是不能关闭的,真要关闭还真要费一番周折。
原来以为setting中的缓存开关是一级缓存呢!错错错!
这里cacheEnabled是全局的二级缓存。学习了,学习了。各个mapper上可以单独去设置当前mapper是否开启。
mybatis的一级缓存,默认情况下都处于开启状态,只能使用自带的PerpetualCache,无法配置第三方缓存
稍后再去研究一下二级缓存。
学习一下:
https://tech.meituan.com/mybatis_cache.html