一、Executor功能概述
每一个sql语句的执行都会先到Executor执行器中在调用相应StatementHandler执行jdbc操作。源码如下SimpleExecutor中的代码片段
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(); //调用StatmentHandler,通过控制器调用jdbc相关操作 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } }
二、Executor继承体系如下
Executor 执行器接口,它有两个实现类,分别是BaseExecutor
和 CachingExecutor
。
BaseExecutor
:是一个抽象类,这种通过抽象的实现接口的方式是适配器设计模式之接口适配
的体现,是 Executor 的默认实现,实现了大部分 Executor 接口定义的功能,降低了接口实现的难度。BaseExecutor 的子类有三个,分别是SimpleExecutor
、ReuseExecutor
和BatchExecutor
。
SimpleExecutor: 简单执行器,是 MyBatis 中默认使用的执行器,每执行一次 update 或 select,就开启一个 Statement 对象,用完就直接关闭 Statement 对象(可以是 Statement 或者是 PreparedStatment 对象)
ReuseExecutor: 可重用执行器,这里的重用指的是重复使用 Statement,它会在内部使用一个 Map 把创建的 Statement 都缓存起来,每次执行 SQL 命令的时候,都会去判断是否存在基于该 SQL 的 Statement 对象,如果存在 Statement 对象并且对应的 connection 还没有关闭的情况下就继续使用之前的 Statement 对象,并将其缓存起来。每个SqlSession 都有一个新的 Executor 对象,所以我们缓存在 ReuseExecutor 上的Statement 作用域是同一个 SqlSession。
BatchExecutor: 批处理执行器,用于将多个SQL一次性输出到数据库
CachingExecutor
: 缓存执行器,先从缓存中查询结果,如果存在,就返回;如果不存在,再委托给 Executor delegate 去数据库中取,delegate 可以是上面任何一个执行器,默认是simpleexecutor
三、Executor创建过程源码分析
(1)创建SqlSession时,可以指定Executor类型,mybatis中ExecutorType枚举类来指定,ExecutorType源码如下,分别指定BaseExecutor下面三个实现类
public enum ExecutorType { SIMPLE, REUSE, BATCH }
(2)根据传递ExecutorType类型可以指定Executor种类,默认不传参就是SimpleExecutor
SqlSession sqlsession=sqlsessionFactory.openSession();
//SqlSession sqlsession=sqlsessionFactory.openSession(ExecutorType.REUSE);
(3)、DefaultSqlSessionFactory中创建执行器,源码如下
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { //定义事物 Transaction tx = null; try { //mybatis配置文件中所有信息都封装到Configuration中,获取环境 ,Environment中有id、datasource、transactionFactory三个属性 final Environment environment = configuration.getEnvironment(); //获取事物工厂 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //根据工厂创建事物对象,直接 return new JdbcTransaction(ds, level, autoCommit); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //创建执行器 final Executor executor = configuration.newExecutor(tx, execType); //默认executor是CachingExecutor 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(); } }
(4)下面看执行器具体创建流程configuration.newExecutor(tx, execType)
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); } //cacheEnabled默认ture开启二级缓存 if (cacheEnabled) { //把简单执行器传递给CachingExecutor中的delegate属性, executor = new CachingExecutor(executor); } //mybatis责任链模式 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}
(5)执行流程入下