本文共 4616 字,大约阅读时间需要 15 分钟。
听说二级缓存是Mapper级的,我找变了mapper也没有找到。
不小心看到MappedStatement有个cache属性。难道是在这里。开始没能串起来。只能网上找。
最后确认这个二级缓存果然就是在MappedStatement。而它又是在Configuration上的啊,这不就成了全局的了吗。
猜:只是缓存的时候以mapper为一个组,然后清理的时候按mapper去清理缓存。所以就成了是Mapper级的了。也就是说是以Mapper去管理这个缓存的。
找的过程就不详细记录了。
要知道二级缓存是可以设置开关的,而且除了全局的开关,还可以在具体的mapper里单独设置。怎么实现的呢?
还有具体查的时候,怎么查的MappedStatement中的cache呢?
还是从最简单的DefaultSqlSession的selectOne(String statement) 方法开始看起。
@Override publicList selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);//就是这里,在学一级缓存的时候就看过这个方法了 } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
这executor.query 有两个实现类。一个是CachingExecutor,另一个是BaseExecutor。我们看CachingExecutor的query
@Override publicList query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache();//从MappedStatement中获取cache。这里我们就知道从这里获取的二级缓存,之前的推测正确,二级缓存就是MappedStatement的cache。 if (cache != null) { flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) {//这里的isUseCache是在Mapper文件中设置的缓存开关 ensureNoOutParams(ms, boundSql); @SuppressWarnings("unchecked") List list = (List ) tcm.getObject(cache, key); if (list == null) { list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//缓存中没有再去BaseExcutor中查(二级缓存没有再找一级缓存) tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } return delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }
这里我们就弄明白了,如何从二级缓存中去数据了。
那么这个executor到底是CachingExecutor还是BaseExecutor呢?
那就要看SqlSession中的executor是如何被创建的
来看这个newExecutor方法,这是我看到的最有价值的一个方法。
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) {//全局设置,是否开启二级缓存,这样看来如果全局关闭,mapper中怎么设置都无法生效啊! executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
开始以为ExecutorType里会有CachingExecutor呢。后来发现不是这里的这个type并不是。
这里有BaseExecutor、SimleExecutor、ReuseExecutor、BatchExecutor、CachingExecutor,是什么关系呢。
SimleExecutor、ReuseExecutor、BatchExecutor是BaseExecutor的子类,CachingExecutor感觉更像是个代理类。
关于二级缓存呢,就看有没有套CachingExecutor这个代理类,跟三个子类没有关系。
二级缓存的开启:
1.在配置文件中天津配置
2.Mapper中添加配置 最简单的配置还可以配置 最大缓存数量 刷新时间 移除策略
3.如果有某个statement不想用二级缓存的话 就可以添加一个配置 这个配置默认为true,只用不使用时才配置
补充一下我的测试代码,开始一直看不到二级缓存到底是怎么生效的,测试代码更让人迷惑,debug看就是找不到。
public static void main( String[] args ) { String resource = "mybatis-config.xml"; try { InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("selectUser",1L); sqlSession.commit(); //这里从网上看到的,的确是不加commit不行,还以为存到别的地方了呢。 SqlSession sqlSession1 = sqlSessionFactory.openSession(); sqlSession1.selectOne("selectUser",1L); user.setName("autotester1"); sqlSession.update("updateUserName",user); user = sqlSession.selectOne("selectUser",1L); System.out.println(user.getName()); //UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //System.out.println(userMapper); } catch (IOException e) { e.printStackTrace(); } }
关键在那个commit,之前没有commit,怎么也不生效。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
从这里学到的:https://www.cnblogs.com/xdp-gacl/p/4270403.html