Executor是mybaits的核心接口之一,他用于执行数据库具体操作,包括但不限于CRUD,commit,rollback等。
Exector有2个子类BaseExecutor和CachingExecutor。
CachingExecutor
只是一个包装(wrapper)类,再原Exector入参的基础上增加了缓存功能。
BaseExecutor
抽象类,它实现了所有公共部分,将核心的具体操作委派给子类:
Executor一共有3个子类:
SimpleExecutor
mybatis默认实现,也是最基础的实现。
ReuseExecutor
增加了一个Statement的缓存Map,key是sql
private final Map<String, Statement> statementMap = new HashMap<String, Statement>();
因为一个SqlSession包含一个Executor:
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
所以该map只有在当前session中有效,在Statement关闭时清楚缓存。
BatchExecutor
用于批量更新操作
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);
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
//当sql和MappedStatement与当前一致时,缓存当前的parameterObject
//这里为什么是取最后一个statement而不是用map去保存,是为了保证操作的一致性。
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
int last = statementList.size() - 1;
stmt = statementList.get(last);
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection);
currentSql = sql;
currentStatement = ms;
statementList.add(stmt);//Statement和MappedStatement一致,为statementList最后一个
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
handler.parameterize(stmt);
//批量执行
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
List<BatchResult> results = new ArrayList<BatchResult>();
if (isRollback) {
return Collections.emptyList();
} else {
for (int i = 0, n = statementList.size(); i < n; i++) {
Statement stmt = statementList.get(i);
BatchResult batchResult = batchResultList.get(i);
try {
batchResult.setUpdateCounts(stmt.executeBatch());//批量执行SQL
MappedStatement ms = batchResult.getMappedStatement();
List<Object> parameterObjects = batchResult.getParameterObjects();
KeyGenerator keyGenerator = ms.getKeyGenerator();
//jdbc3.0主键生成方式
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) {
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
} catch (BatchUpdateException e) {
...
}
results.add(batchResult);
}
return results;
}
} finally {
for (Statement stmt : statementList) {//关闭所有链接
closeStatement(stmt);
}
...
}
SqlSession周期的一级缓存
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;
}