一级缓存
一级缓存是SqlSession级别的,SqlSessionFactory在openSession的时候会创建一个本地缓存变量。
相关源码
// org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
// 创建SqlSession
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
...
}
// 根据配置类的执行器类型创建执行器
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) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
// SimpleExecutor
public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}
// BaseExecutor
protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<>();
// 一级缓存
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}
// PerpetualCache
public class PerpetualCache implements Cache {
private final String id;
private final Map<Object, Object> cache = new HashMap<>();
}
// 执行查询时
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
...
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);
}
...
// LocalCacheScope设置为STATEMENT,一级缓存不会生效
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache();
}
return list;
}
// 查询数据库并放入缓存
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
} 说明
- 默认开启。
- localCacheScope设置为STATEMENT时,sqlSession执行多次查询时每次查询结束后都会清空一级缓存。
- 缓存的key与Namespance、SQL语句相关。
- 一级缓存和执行器类一对一。
二级缓存
与一级缓存的区别
- 二级缓存是应用级别的缓存, 与Configuration类一对一。
- 缓存的key是MapperXML的Namespace,Value和一级缓存的类(PerpetualCache)一样。
- SqlSession事务提交(或关闭)的时候才会存二级缓存,而一级缓存在查询到结果后就存缓存了;但是执行查询时优先从二级缓存中获取查询结果,未命中二级缓存后,才会去一级缓存中获取结果。
启用二级缓存
- 修改settings
<setting name="cacheEnabled" value="true" />
- 修改MapperXML
<cache />
二级缓存失效
- 同一命名空间,执行了增删改时,会清空缓存。当存在联合查询时,可以通过设置
<cache-ref namespace="" />清空指定命名空间的的二级缓存,但是只能指定一个namespace。

京公网安备 11010502036488号