源码分析-Mybatis源码阅读-执行器

源码解析-Mybatis
01 源码分析-Mybatis源码阅读准备
02 源码分析-Mybatis源码阅读-会话层
03 源码分析-Mybatis源码阅读-执行器
04 源码分析-Mybatis源码阅读-Statement语句处理器
05 源码分析-Mybatis源码阅读-参数处理器
06 源码分析-Mybatis源码阅读-结果集处理器
07 源码分析-Mybatis源码阅读-主键生成器
08 源码分析-Mybatis源码阅读-懒加载机制
09 源码分析-Mybatis源码阅读-游标
10 源码分析-Mybatis源码阅读-类型处理器
11 源码分析-Mybatis源码阅读-缓存
12 源码分析-Mybatis源码阅读-Mapper代理

一 执行器包下类的说明

执行器的代码,主要在包org.apache.ibatis.executor中,其实除了执行器之外,还包含语句处理器、参数处理器、结果集处理器等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
.
└── org
└── apache
└── ibatis
└── executor
   ├── BaseExecutor.java 抽象基础执行器
   ├── BatchExecutor.java 批执行器
   ├── BatchExecutorException.java 批执行器异常(对java.sql.BatchUpdateException的包装)
   ├── BatchResult.java 批处理结果
   ├── CachingExecutor.java 缓存执行器
   ├── ErrorContext.java 错误信息上下文
   ├── ExecutionPlaceholder.java 执行占位符
   ├── Executor.java 执行器接口
   ├── ExecutorException.java 执行器异常
   ├── ResultExtractor.java 结果提取器
   ├── ReuseExecutor.java 重用执行器 重用针对的是Statement的重用
   ├── SimpleExecutor.java 简单执行器
   ├── keygen
   │   ├── Jdbc3KeyGenerator.java 主键生成器(自增的,也就是数据库自增后如果需要知道值,就用这个,这个是将自增结果回填到对象中)
   │   ├── KeyGenerator.java 主键生成器接口
   │   ├── NoKeyGenerator.java 不生成主键的生成器
   │   └── SelectKeyGenerator.java 主键生成器(在mapper里面配置的selectKey生成方式)
   ├── loader
   │   ├── AbstractEnhancedDeserializationProxy.java 抽象增强型反序列化代理
   │   ├── AbstractSerialStateHolder.java 抽象串行状态保持器
   │   ├── CglibProxyFactory.java 已弃用的Cglib代理工厂类
   │   ├── JavassistProxyFactory.java 已启用的Javassist代理工厂类
   │   ├── ProxyFactory.java 代理工厂接口
   │   ├── ResultLoader.java 结果集加载器
   │   ├── ResultLoaderMap.java 要懒加载的属性Map
   │   ├── WriteReplaceInterface.java 代理对象可能需要继承的接口(包含writeReplace方法)
   │   ├── cglib
   │   │   ├── CglibProxyFactory.java Cglib代理工厂
   │   │   └── CglibSerialStateHolder.java Cglib串行状态保持器
   │   └── javassist
   │      ├── JavassistProxyFactory.java Javassist代理工厂
   │      └── JavassistSerialStateHolder.java Javassist串行状态保持器
   ├── parameter
   │   └── ParameterHandler.java 参数处理器接口
   ├── result
   │   ├── DefaultMapResultHandler.java 默认Map结果处理器
   │   ├── DefaultResultContext.java 默认的结果上下文
   │   ├── DefaultResultHandler.java 默认的结果上下文处理器
   │   └── ResultMapException.java 结果集异常
   ├── resultset
   │   ├── DefaultResultSetHandler.java 默认的结果集处理器
   │   ├── ResultSetHandler.java 结果集处理器
   │   └── ResultSetWrapper.java 结果集包装器
   └── statement
   ├── BaseStatementHandler.java 基本的语句处理器
   ├── CallableStatementHandler.java 支持回调的语句处理器
   ├── PreparedStatementHandler.java 预处理的语句处理器
   ├── RoutingStatementHandler.java 路由语句处理程序
   ├── SimpleStatementHandler.java 简单语句处理器
   ├── StatementHandler.java 语句处理器接口
   └── StatementUtil.java 语句工具类

二 执行器相关源码解读

首先,先看一下mybatis给我们提供了哪些执行器,如下图:

image-20210514183500566

以上执行器中BaseExecutor使用了模板方法模式,CachingExecutor使用了装饰模式,了解这两个模式有助于我们更容易阅读源码。

先来看BaseExecutor的关键源码解析如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
....
/**
* 基础执行器 主要通过模板方法 定义了查询、修改的算法流程
* @author Clinton Begin
*/
public abstract class BaseExecutor implements Executor {

....
/**
* 更新数据库数据,INSERT/UPDATE/DELETE三种操作都会调用该方法
* @param ms 映射语句
* @param parameter 参数对象
* @return 数据库操作结果
* @throws SQLException
*/
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
// 执行器已经关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 清理本地缓存
clearLocalCache();
// 返回调用子类进行操作
return doUpdate(ms, parameter);
}

....
/**
* 查询数据库中的数据
* @param ms 映射语句
* @param parameter 参数对象
* @param rowBounds 翻页限制条件
* @param resultHandler 结果处理器
* @param key 缓存的键
* @param boundSql 查询语句
* @param <E> 结果类型
* @return 结果列表
* @throws SQLException
*/
@SuppressWarnings("unchecked")
@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) {
// 本地缓存中有结果,则对于CALLABLE语句还需要绑定到IN/INOUT参数上
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();
// 如果本地缓存的作用域为STATEMENT,则立刻清除本地缓存
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}

....

再看一下 SimpleExecutor 简单执行器,主要是在操作查询和更新之前,先通过语句处理器StatementHandler处理好语句,之后再执行查询或更新操作,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* 简单执行器
* @author Clinton Begin
*/
public class SimpleExecutor extends BaseExecutor {

public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}

/**
* 操作数据库更新
* @param ms 映射语句
* @param parameter 参数
* @return
* @throws SQLException
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
// 新建语句处理器
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
// 执行sql语句
return handler.update(stmt);
} finally {
// 关闭statement
closeStatement(stmt);
}
}

/**
* 操作数据库查询
*
* @param ms 映射语句
* @param parameter 参数对象
* @param rowBounds 翻页限制条件
* @param resultHandler 结果处理器
* @param boundSql 查询语句
* @param <E> 结果类型
* @return
* @throws SQLException
*/
@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());
// 执行sql语句 并传入结果处理器 处理好结果返回
return handler.query(stmt, resultHandler);
} finally {
// 关闭statement
closeStatement(stmt);
}
}

@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
Cursor<E> cursor = handler.queryCursor(stmt);
// 当所有结果集关闭后关闭statement
stmt.closeOnCompletion();
return cursor;
}

@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
return Collections.emptyList();
}

/**
* 获取 Statement 对象
* @param handler 语句处理器
* @param statementLog 日志
* @return
* @throws SQLException
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
// 创建 Statement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
// 为语句设置参数
handler.parameterize(stmt);
return stmt;
}

}

然后,我们再看一下重用执行器ReuseExecutor,相比与SimpleExecutor主要是缓存了Statement,使得Statement可重用。源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* 重用执行器 重用针对的是Statement的重用
* @author Clinton Begin
*/
public class ReuseExecutor extends BaseExecutor {

/**
* statement对象缓存
*/
private final Map<String, Statement> statementMap = new HashMap<>();

public ReuseExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}

/**
* 操作数据库更新
* @param ms 映射语句
* @param parameter 参数
* @return
* @throws SQLException
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Configuration configuration = ms.getConfiguration();
// 新建语句处理器
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
// 执行sql语句
return handler.update(stmt);
}

/**
* 操作数据库查询
*
* @param ms 映射语句
* @param parameter 参数对象
* @param rowBounds 翻页限制条件
* @param resultHandler 结果处理器
* @param boundSql 查询语句
* @param <E> 结果类型
* @return
* @throws SQLException
*/
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
// 新建语句处理器
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
// 执行sql语句 并传入结果处理器 处理好结果返回
return handler.query(stmt, resultHandler);
}

@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
// 新建语句处理器
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.queryCursor(stmt);
}

@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
for (Statement stmt : statementMap.values()) {
closeStatement(stmt);
}
statementMap.clear();
return Collections.emptyList();
}

/**
* 获取statement
* @param handler 语句处理器
* @param statementLog 日志
* @return
* @throws SQLException
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 获取执行SQL
BoundSql boundSql = handler.getBoundSql();
String sql = boundSql.getSql();
// 判断SQL是否已经有Statement
if (hasStatementFor(sql)) {
// 直接从map中获取Statement
stmt = getStatement(sql);
// 设置事务超时
applyTransactionTimeout(stmt);
} else {
// 获取连接
Connection connection = getConnection(statementLog);
// 获取statement
stmt = handler.prepare(connection, transaction.getTimeout());
// 缓存statement
putStatement(sql, stmt);
}
handler.parameterize(stmt);
return stmt;
}

private boolean hasStatementFor(String sql) {
try {
Statement statement = statementMap.get(sql);
return statement != null && !statement.getConnection().isClosed();
} catch (SQLException e) {
return false;
}
}

private Statement getStatement(String s) {
return statementMap.get(s);
}

private void putStatement(String sql, Statement stmt) {
statementMap.put(sql, stmt);
}

}

再来看看批处理执行器BatchExecutor,相比于简单执行器SimpleExecutor,批处理执行器主要区别在于doUpdate方法(即更新、插入、删除等操作)可以进行批量操作。而针对查询,和SimpleExecutor是基本一样的,只是在查询之前需要先执行批处理刷新操作,确保前面的doUpdate批处理操作能先预处理到数据库中,查询才能查询出来。批处理执行器的源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

/**
* 批处理执行器 主要是针对 doUpdate支持批处理
* @author Jeff Butler
*/
public class BatchExecutor extends BaseExecutor {

public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;

private final List<Statement> statementList = new ArrayList<>();
private final List<BatchResult> batchResultList = new ArrayList<>();
private String currentSql;
private MappedStatement currentStatement;

public BatchExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}

/**
* 操作数据库更新
* @param ms 映射语句
* @param parameterObject 参数
* @return
* @throws SQLException
*/
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
final Configuration configuration = ms.getConfiguration();
// 创建语句处理器
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
// 获取绑定的sql
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
// 如果当前
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
int last = statementList.size() - 1;
stmt = statementList.get(last);
// 设置事务超时时间
applyTransactionTimeout(stmt);
// 为语句设置参数
handler.parameterize(stmt);// fix Issues 322
// 获取批处理结果
BatchResult batchResult = batchResultList.get(last);
// 追加参数值对象
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
// 创建statement
stmt = handler.prepare(connection, transaction.getTimeout());
// 为语句设置参数
handler.parameterize(stmt); // fix Issues 322
// 记录当前执行器对象最后一次执行的SQL
currentSql = sql;
// 记录当前执行器对象最后一次执行的statement
currentStatement = ms;
// 记录当前执行器创建的所有statement
statementList.add(stmt);
// 记录所有statement的批处理结果
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// 追加参数集合
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}

/**
* 操作数据库查询
*
* @param ms 映射语句
* @param parameterObject 参数对象
* @param rowBounds 翻页限制条件
* @param resultHandler 结果处理器
* @param boundSql 查询语句
* @param <E> 结果类型
* @return
* @throws SQLException
*/
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException {
Statement stmt = null;
try {
// 刷新语句
flushStatements();
Configuration configuration = ms.getConfiguration();
// 新建语句处理器
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
Connection connection = getConnection(ms.getStatementLog());
// 新建语句处理器
stmt = handler.prepare(connection, transaction.getTimeout());
// 执行sql语句 并传入结果处理器 处理好结果返回
handler.parameterize(stmt);
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}

@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
flushStatements();
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Connection connection = getConnection(ms.getStatementLog());
Statement stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
Cursor<E> cursor = handler.queryCursor(stmt);
stmt.closeOnCompletion();
return cursor;
}

/**
* 刷新批处理语句
* @param isRollback
* @return
* @throws SQLException
*/
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
List<BatchResult> results = new ArrayList<>();
if (isRollback) {
return Collections.emptyList();
}
// 遍历每个statement
for (int i = 0, n = statementList.size(); i < n; i++) {
Statement stmt = statementList.get(i);
// 设置超时时间
applyTransactionTimeout(stmt);
// 获取每个statement的批处理结果
BatchResult batchResult = batchResultList.get(i);
try {
// 设置批处理更新数量
batchResult.setUpdateCounts(stmt.executeBatch());
// 获取映射语句
MappedStatement ms = batchResult.getMappedStatement();
// 获取批处理结果的参数对象
List<Object> parameterObjects = batchResult.getParameterObjects();
// 获取主键生成器
KeyGenerator keyGenerator = ms.getKeyGenerator();
// 如果是数据库自增主键生成器
if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
// 把主键设置到参数值对象中
jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141 如果不是不生成主键
for (Object parameter : parameterObjects) {
// 执行完sql之后再获取主键
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
// Close statement to close cursor #1109
closeStatement(stmt);
} catch (BatchUpdateException e) {
StringBuilder message = new StringBuilder();
message.append(batchResult.getMappedStatement().getId())
.append(" (batch index #")
.append(i + 1)
.append(")")
.append(" failed.");
if (i > 0) {
message.append(" ")
.append(i)
.append(" prior sub executor(s) completed successfully, but will be rolled back.");
}
throw new BatchExecutorException(message.toString(), e, results, batchResult);
}
results.add(batchResult);
}
return results;
} finally {
for (Statement stmt : statementList) {
closeStatement(stmt);
}
currentSql = null;
statementList.clear();
batchResultList.clear();
}
}

}

然后,我们再来看看缓存执行器CachingExecutor,缓存执行器,顾名思义,就是把查询的结果缓存起来,相同的sql和入参第二次进来触发查询,则会命中缓存直接返回,当然查询的中途不能有其他update操作,否则缓存都会被清空。缓存执行器的源码解析如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
* 缓存执行器
* @author Clinton Begin
* @author Eduardo Macarron
*/
public class CachingExecutor implements Executor {

/**
* 被装饰的执行器
*/
private final Executor delegate;
/**
* 事务缓存管理器
*/
private final TransactionalCacheManager tcm = new TransactionalCacheManager();

public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}

@Override
public Transaction getTransaction() {
return delegate.getTransaction();
}

@Override
public void close(boolean forceRollback) {
try {
// issues #499, #524 and #573
if (forceRollback) {
tcm.rollback();
} else {
tcm.commit();
}
} finally {
delegate.close(forceRollback);
}
}

@Override
public boolean isClosed() {
return delegate.isClosed();
}

/**
* 更新数据库数据,INSERT/UPDATE/DELETE三种操作都会调用该方法
* @param ms 映射语句
* @param parameterObject 参数对象
* @return 数据库操作结果
* @throws SQLException
*/
@Override
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
// 根据要求判断语句执行前是否要清除二级缓存,如果需要,清除二级缓存
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}

@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
flushCacheIfRequired(ms);
return delegate.queryCursor(ms, parameter, rowBounds);
}

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

/**
* 查询数据库中的数据
* @param ms 映射语句
* @param parameterObject 参数对象
* @param rowBounds 翻页限制条件
* @param resultHandler 结果处理器
* @param key 缓存的键
* @param boundSql 查询语句
* @param <E> 结果类型
* @return 结果列表
* @throws SQLException
*/
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
// 获取MappedStatement对应的缓存,可能的结果有:该命名空间的缓存、共享的其它命名空间的缓存、无缓存
Cache cache = ms.getCache();
// 如果映射文件未设置<cache>或<cache-ref>则,此处cache变量为null
// 存在缓存
if (cache != null) {
// 根据要求判断语句执行前是否要清除二级缓存,如果需要,清除二级缓存
flushCacheIfRequired(ms);
// 该语句使用缓存且没有输出结果处理器
if (ms.isUseCache() && resultHandler == null) {
// 二级缓存不支持含有输出参数的CALLABLE语句,故在这里进行判断
ensureNoOutParams(ms, boundSql);
// 从缓存中读取结果
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
// 缓存中没有结果
if (list == null) {
// 交给被包装的执行器执行
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
// 缓存被包装执行器返回的结果
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
// 交由被包装的实际执行器执行
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

@Override
public List<BatchResult> flushStatements() throws SQLException {
return delegate.flushStatements();
}

@Override
public void commit(boolean required) throws SQLException {
delegate.commit(required);
tcm.commit();
}

@Override
public void rollback(boolean required) throws SQLException {
try {
delegate.rollback(required);
} finally {
if (required) {
tcm.rollback();
}
}
}

private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
throw new ExecutorException("Caching stored procedures with OUT params is not supported. Please configure useCache=false in " + ms.getId() + " statement.");
}
}
}
}

@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}

@Override
public boolean isCached(MappedStatement ms, CacheKey key) {
return delegate.isCached(ms, key);
}

@Override
public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
delegate.deferLoad(ms, resultObject, property, key, targetType);
}

@Override
public void clearLocalCache() {
delegate.clearLocalCache();
}

/**
* 根据要求判断语句执行前是否要清除二级缓存,如果需要,清除二级缓存
* 注意:默认情况下,非SELECT语句的isFlushCacheRequired方法会返回true
* 执行的非Select语句,一般都会清空缓存
* @param ms MappedStatement
*/
private void flushCacheIfRequired(MappedStatement ms) {
// 获取MappedStatement对应的缓存
Cache cache = ms.getCache();
// 存在缓存且该操作语句要求执行前清除缓存
if (cache != null && ms.isFlushCacheRequired()) {
// 清除事务中的缓存
tcm.clear(cache);
}
}

@Override
public void setExecutorWrapper(Executor executor) {
throw new UnsupportedOperationException("This method should not be called");
}

}

最后简单说明一下,ClosedExecutor执行器,主要是用于标识执行器已经关闭了,后续需要再执行,则需要新建执行器执行。