看了通过源码分析MyBatis的缓存这篇文章后,自己跟着源码过了一遍,对mybatis的一级缓存和二级缓存有了更清楚的认识。
一级缓存是SqlSession级别的,同一个sqlSession在第二次执行一个相同参数的select语句并且第一次执行后没有对数据进行更新,就会直接从缓存取值,而不再进行查找。通过阅读源码了解了这个过程,首先org.apache.ibatis.session.defaults.DefaultSqlSession.select(String, Object, RowBounds, ResultHandler)方法会调用executor.query(ms, wrapCollection(parameter), rowBounds, handler),然后分析executor的类型,在org.apache.ibatis.session.defaults.DefaultSqlSessionFactory类中,openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean)方法的Executor executor = configuration.newExecutor(tx, execType) 语句实例化executor,代码如下,在SqlMapConfig.xml中cacheEnabled默认为true,即一级缓存默认开启,故executor为CachingExecutor类型。
/* */ public Executor newExecutor(Transaction transaction, ExecutorType executorType) { /* 540 */ executorType = executorType == null ? defaultExecutorType : executorType; /* 541 */ executorType = executorType == null ? ExecutorType.SIMPLE : executorType; /* */ Executor executor; /* 543 */ if (ExecutorType.BATCH == executorType) { /* 544 */ executor = new BatchExecutor(this, transaction); } else { Executor executor; /* 545 */ if (ExecutorType.REUSE == executorType) { /* 546 */ executor = new ReuseExecutor(this, transaction); /* */ } else /* 548 */ executor = new SimpleExecutor(this, transaction); /* */ } /* 550 */ if (cacheEnabled) { /* 551 */ executor = new CachingExecutor(executor); /* */ } /* 553 */ Executor executor = (Executor)interceptorChain.pluginAll(executor); /* 554 */ return executor; /* */ } /* */
在org.apache.ibatis.executor.CachingExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql)方法中首先获取二级缓存,由于二级缓存为空,执行该语句
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
delegate对象为org.apache.ibatis.executor.SimpleExecutor类型,继承自org.apache.ibatis.executor.BaseExecutor类,query方法如下
BaseExecutor的属性localCache是个PerpetualCache类型的实例,PerpetualCache类是实现了MyBatis的Cache缓存接口的实现类之一,内部有个Map<object, object>类型的属性用来存储缓存数据。 这个localCache的类型在BaseExecutor内部是写死的。 这个localCache就是一级缓存!
在数据更改时会清空缓存。
二级缓存是基于namespace的,必须在sqlSession提交或关闭才会生效。需要在mapper配置文件加上<cache />。
原文地址:https://www.cnblogs.com/csdeblog/p/9740769.html