文章目录

  • ​​1.SqlSession介绍​​
  • ​​2.Executor介绍​​
  • ​​3.Executor的创建​​
  • ​​4.Sql执行/Executor 源码分析​​

1.SqlSession介绍

SqlSession是一个接口, 有两个实现类, DefaultSqlSession 和 SqlSessionManager(弃用)

SqlSession是Mybatis用于和数据库交互的顶级类, 通常和ThreadLocal绑定, 一个会话使用一个SqlSession, 使用完毕后close。

public class DefaultSqlSession implements SqlSession {

private final Configuration configuration;
private final Executor executor;
}

SqlSession中有两个重要的属性, 一个是configuration与初始化时候的相同, 一个是Executor执行器。

2.Executor介绍

mybatis (Sql执行流程 + Executor执行器 + 源码分析) (四)_sql

  • Executor接口:有两个实现类BaseExecutor、CachingExecutor
  • BaseExecutor:是一个抽象类,抽象类实现接口是”适配器模式“的体现,为了方便下一级实现类对接口中方法的实现;BaseExecutor有三个子类分别是simpleExecutor、ResuseExecutor、BatchExecutor
  • SimpleExecutor:是MyBatis中默认使用的执行器. 每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。(可以是Statement或PrepareStatement对象)
  • ReuseExecutor:可重用执行器,这里的重用指的是重复使用Statement. 它会在内部利用一个Map把创建的Statement都缓存起来,每次在执行一条SQL语句时,它都会去判断之前是否存在基于该SQL缓存的Statement对象,存在而且之前缓存的Statement对象对应的Connection还没有关闭的时候就继续用之前的Statement对象,否则将创建一个新的Statement对象,并将其缓存起来。因为每一个新的SqlSession都有一个新的Executor对象,所以我们缓存在ReuseExecutor上的Statement的作用域是同一个SqlSession
  • BatchExecutor:批处理执行器,.用于将多个sql语句一次性输送到数据库执行.
  • CachingExecutor:缓存执行器, 先从缓存中获取查询结果,存在就返回,不存在,再委托给Executor delegate去数据库取,delegate可以是上面任一的SimpleExecutor、ReuseExecutor、BatchExecutor

3.Executor的创建

在SqlSessionFactory创建完成后,调用openSession方法:

public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}

DefaultSqlSessionFactory#openSessionFromDataSource()

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;

DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
}

return var8;
}

执行器对象是由Coniguration对象负责创建的​​.Configuration​​​对象会根据得到​​ExecutorType​​​创建对应的​​Excecutor​​​对象,并把这个Excecutor对象传给​​SqlSession​​对象

这里默认的ExecutorType为​​ExecutorType.SIMPLE​

@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

mybatis (Sql执行流程 + Executor执行器 + 源码分析) (四)_java_02

mybatis (Sql执行流程 + Executor执行器 + 源码分析) (四)_缓存_03

4.Sql执行/Executor 源码分析

mybatis (Sql执行流程 + Executor执行器 + 源码分析) (四)_ide_04

@Override
public <E> List<E> selectList(String statement) {
return this.selectList(statement, null);
}

@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}

@Override
public <E> List<E> 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();
}
}

最后sql的执行还是Eexcutor执行器进行的

BaseExector.query()

@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}

@Override
public <E> List<E> 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<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);
}
} 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;
}

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;
}

SimpleExecutor.doQuery()

@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}

mybatis (Sql执行流程 + Executor执行器 + 源码分析) (四)_ide_05

说明Executor交给了StatementHandler进行执行。

StatementHandler下一章介绍