一、SimpleExecutor
SimpleExecutor继承BaseExecutor
主要实现:doUpdate、doQuery、doFlushStatements
可以看代码主要是:
1、获取声明处理类:StatementHandler handler
2、获取声明类:stmt = prepareStatement(handler, ms.getStatementLog());
3、处理声明,执行SQL处理
二、ReuseExecutor
与SimpleExecutor不同的是:重用声明
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
BoundSql boundSql = handler.getBoundSql();
String sql = boundSql.getSql();
if (hasStatementFor(sql)) {
stmt = getStatement(sql);
} else {
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection);
putStatement(sql, stmt);
}
handler.parameterize(stmt);
return stmt;
}
SQL语句一样的,就用同样的声明。不过这个好像也仅仅是同一个session内的有效。
三、BatchExecutor
先看update
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;
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);
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
handler.parameterize(stmt);
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
if
(sql.equals(currentSql) && ms.equals(currentStatement))
表明同一个SQL语句使用同一个申明,应用场景很简单,就是我们的批量删除和批量插入,在没有参数的SQL语句他们就是一样的,不一样的只是参数而已。具体参数处理在StatementHandler里面去设置的。也是同一个session内的批量操作。是不是很奇怪没有提交?看完查询再说:
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(this, ms, parameterObject, rowBounds, resultHandler, boundSql);
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection);
handler.parameterize(stmt);
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
重点flushStatements,为什么这里会做这件事呢?因为在同一session里面如果又是批量操作,又是查询的话,那么就必须保证批量操作数据提交上去了。也就是为什么有这个,这个方法主要的事情归结到doFlushStatements,就是批量更新提交。查询有提交,批量更新那个怎么没有提交?在sqlsession里面commit调用BaseExecutor里面commit:
public void commit(boolean required) throws SQLException {
if (closed) throw new ExecutorException("Cannot commit, transaction is already closed");
clearLocalCache();
flushStatements();
if (required) {
transaction.commit();
}
}
flushStatements();注意使用批量的时候,如果不开启批量模式,是没有使用批量更新的,使用sessionFactory.openSession(ExecutorType.BATCH,
false);
网上大部分例子都没有正确使用批量更新,因为mybatis默认是SimpleExecutor执行器
四、CachingExecutor
缓存执行器,顾名思义跟缓存有关系,这里的缓存是全局缓存,configuration里面的cacheEnabled参数决定,默认为true
也就是默认是开启全局缓存,但是只是这里开启就可以吗?详细看看CachingExecutor这个类:
先看创建这个类:
public CachingExecutor(Executor delegate) {
this(delegate, false);
}
public CachingExecutor(Executor delegate, boolean autoCommit) {
this.delegate = delegate;
this.autoCommit = autoCommit;
}
装饰模式,也就是说缓存执行器,增强了其他的执行器,不同的是他先执行缓存处理。(以后需要加缓存时可以借鉴)
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}
更新先flush缓存
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
if (!dirty) {
cache.getReadWriteLock().readLock().lock();
try {
@SuppressWarnings("unchecked")
List<E> cachedList = (List<E>) cache.getObject(key);
if (cachedList != null) return cachedList;
} finally {
cache.getReadWriteLock().readLock().unlock();
}
}
List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
return list;
}
}
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
查询重点:
Cache cache = ms.getCache(); 看mapper上配置缓存没有,如果有执行缓存逻辑,所以默认全局缓存开启后,每个mapper上必须配置是否使用缓存,缓存才有效。这个缓存在MappedStatement上,所以是全局的,非仅仅在session内有效。