2019独角兽企业重金招聘Python工程师标准>>>
注:Mybatis的版本是3.5.0。
1.LocalCache(一级缓存)
先上一张图
图1 Mybatis查询时使用LocalCache
LocalCache,也被称为一级缓存,有如下特点:
- 它的生命周期与SqlSession一致。
- 底层用HashMap实现,没有缓存内容更新和过期。
- 有个多个SqlSession时,且有数据库写,会出现脏读的情况,一级缓存慎用,或者将Scope设置为Statement。
LocalCacheScope有俩个值,如下List-1所示
List-1 LocalCacheScope的值有枚举值
package org.apache.ibatis.session;
/**
* @author Eduardo Macarron
*/
public enum LocalCacheScope {
SESSION, STATEMENT
}
Configuration中localCacheScope默认值是SESSION,如下List-2所示
List-2 Configuration的属性localCacheScope默认值是SESSION
package org.apache.ibatis.session;
.....
/**
* @author Clinton Begin
*/
public class Configuration {
......
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
......
为什么说LocalCache生命周期与SqlSession一致,如List-3所示:
List-3 DefaultSqlSessionFactory的openSessionFromDataSource和openSessionFromConnection
package org.apache.ibatis.session.defaults;
......
/**
* @author Clinton Begin
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory {
......
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);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException e) {
// Failover to true, as most poor drivers
// or databases won't support transactions
autoCommit = true;
}
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
......
List-3中的方法openSessionFromDataSource和方法openSessionFromConnection中的configuration.newExecutor(tx, execType)的实现如下List-4所示。每次实例化一个DefaultSqlSession时,都会实例化一个SimpleExecutor,而用于一级缓存的localCache就在BaseExecutor中,BaseExecutor是SimpleExecutor的父类。所以当SqlSession对象被销毁时,它的Executor也被销毁,所以localCache也被销毁。
List-4 newExecutor中默认情况下新建SimpleExecutor
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;
}
2.参考
1.https://www.jianshu.com/p/c553169c5921,这篇博客写的挺好的。
2.Mybatis源码,去Github上下载。