前言
在前面的两个章节中,我们介绍了SqlSession和自定义Mapper的执行流程,自定义Mapper最终的执行也是通过SqlSession去执行对应的sql的.SqlSession的内部是因为维护了一个Executor,所有的操作也是通过Executor完成.这一章我们就来学习Executor的源码
1. Executor
1.1 结构介绍
Executor有两个实现类. 一个CachingExecutor还有一个抽象类BaseExecutor. BaseExecutor又有四个子类SimpleExecutor, 一个内部类ClosedExecutor.ReuseExecutor和BatchExecutor
1.2 CachingExecutor
CachingExecutor的内部维护了一个Executor,它的方法都是通过内部的delegate完成的,只不过是在执行过程中加入了一些缓存的操作,我们挑选核心的crud的方法进行学习
public class CachingExecutor implements Executor {
/**
* 执行代理, 实际crud的执行者
*/
private final Executor delegate;
/**
* 事务缓存管理器
*/
private final TransactionalCacheManager tcm = new TransactionalCacheManager();
/**构造函数
* @param delegate 代理对象, 为BaseExecutor的子类
*/
public CachingExecutor(Executor delegate) {
this.delegate = delegate;
//设置代理类的包装为当期的cacheExecutor
delegate.setExecutorWrapper(this);
}
/**获取事务
* @return 事务
*/
@Override
public Transaction getTransaction() {
return delegate.getTransaction();
}
/**关闭executor
* @param forceRollback 是否强制回滚
*/
@Override
public void close(boolean forceRollback) {
try {
// issues #499, #524 and #573
if (forceRollback) {
//如果需要强制回滚,则回滚
tcm.rollback();
} else {
//否则提交
tcm.commit();
}
} finally {
//关闭代理执行器
delegate.close(forceRollback);
}
}
/**是否关闭
* @return 是否关闭
*/
@Override
public boolean isClosed() {
//返回代理对象的关闭状态
return delegate.isClosed();
}
/**执行更新语句
* @param ms MappedStatement
* @param parameterObject 参数
* @return 影响的行数
* @throws SQLException 异常
*/
@Override
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
//根据配置清除缓存
flushCacheIfRequired(ms);
//调用代理类的更新
return delegate.update(ms, parameterObject);
}
/**查询游标
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param <E> 返回对象的泛型
* @return 游标列表
* @throws SQLException 异常
*/
@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
//根据配置清除缓存
flushCacheIfRequired(ms);
//调用代理类的查询游标
return delegate.queryCursor(ms, parameter, rowBounds);
}
/**执行带结果返回的查询
* @param ms MappedStatement
* @param parameterObject 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param <E> 返回对象的泛型
* @return 对象列表
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//获取boundSql
BoundSql boundSql = ms.getBoundSql(parameterObject);
//计算缓存key
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
//调用query
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
/**执行带结果返回的查询
* @param ms MappedStatement
* @param parameterObject 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param key 缓存key
* @param boundSql 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 {
//从statement中获取缓存
Cache cache = ms.getCache();
if (cache != null) {
//如果statement中配置了<cache>
//根据配置清除缓存
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
//如果使用缓存,并且结果处理器为空
//确保未使用输出参数
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);
}
/**执行批量语句
* @return 批处理结果
* @throws SQLException 异常
*/
@Override
public List<BatchResult> flushStatements() throws SQLException {
return delegate.flushStatements();
}
/**提交事务
* @param required 是否需要
* @throws SQLException 异常
*/
@Override
public void commit(boolean required) throws SQLException {
//提交代理类
delegate.commit(required);
//事务缓存管理器提交
tcm.commit();
}
/**回滚事务
* @param required 是否需求
* @throws SQLException 异常
*/
@Override
public void rollback(boolean required) throws SQLException {
try {
//回滚代理类
delegate.rollback(required);
} finally {
if (required) {
//事务缓存管理器回滚
tcm.rollback();
}
}
}
/**验证mapperStatement中没有输出类型的参数
* @param ms MappedStatement
* @param boundSql boundSql
*/
private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
//判断callable类型的statement
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
//如果参数类型不为IN,抛出异常
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.");
}
}
}
}
/**创建一个缓存的key对象
* @param ms MappedStatement
* @param parameterObject 参数对象
* @param rowBounds 分页对象
* @param boundSql boundSql
* @return 计算出的缓存key
*/
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
//调用代理类创建缓存key
return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}
/**当前CacheKey是否有对应的缓存
* @param ms MappedStatement
* @param key CacheKey
* @return 是否有对应的缓存
*/
@Override
public boolean isCached(MappedStatement ms, CacheKey key) {
//调用代理类判断是否缓存
return delegate.isCached(ms, key);
}
/**延迟加载
* @param ms MappedStatement
* @param resultObject 元数据对象
* @param property 属性名
* @param key 缓存key
* @param targetType 对象类型
*/
@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();
}
/**根据需要清空二级缓存
* @param ms MappedStatement
*/
private void flushCacheIfRequired(MappedStatement ms) {
Cache cache = ms.getCache();
//如果开启了二级缓存,并且配置了刷新缓存
if (cache != null && ms.isFlushCacheRequired()) {
//清除二级缓存
tcm.clear(cache);
}
}
/**设置Executor的包装Executor
* @param executor 包装的executor
*/
@Override
public void setExecutorWrapper(Executor executor) {
//CacheExecutor不支持设置包装器
throw new UnsupportedOperationException("This method should not be called");
}
}
1.3 BaseExecutor
public abstract class BaseExecutor implements Executor {
private static final Log log = LogFactory.getLog(BaseExecutor.class);
/**
* 事务
*/
protected Transaction transaction;
/**
* 包装当前对象的Executor
*/
protected Executor wrapper;
/**
* 延迟加载的队列
*/
protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
/**
* 本地缓存, 一级缓存
*/
protected PerpetualCache localCache;
/**
* 本地输出参数的一级缓存
*/
protected PerpetualCache localOutputParameterCache;
/**
* 核心配置对象
*/
protected Configuration configuration;
/**
* //todo
*/
protected int queryStack;
/**
* 是否关闭
*/
private boolean closed;
/**受保护的构造方法
* @param configuration 核心配置对象
* @param transaction 事务
*/
protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<>();
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}
/**获取事务
* @return 事务
*/
@Override
public Transaction getTransaction() {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
return transaction;
}
/**关闭executor
* @param forceRollback 是否强制回滚
*/
@Override
public void close(boolean forceRollback) {
try {
try {
//根据需要回滚
rollback(forceRollback);
} finally {
if (transaction != null) {
//关闭事务
transaction.close();
}
}
} catch (SQLException e) {
// Ignore. There's nothing that can be done at this point.
log.warn("Unexpected exception on closing transaction. Cause: " + e);
} finally {
//清除引用
transaction = null;
deferredLoads = null;
localCache = null;
localOutputParameterCache = null;
closed = true;
}
}
/**是否关闭
* @return 是否关闭
*/
@Override
public boolean isClosed() {
return closed;
}
/**执行更新语句
* @param ms MappedStatement
* @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();
//执行doUpdate
return doUpdate(ms, parameter);
}
/**执行批量语句
* @return 批处理结果
* @throws SQLException 异常
*/
@Override
public List<BatchResult> flushStatements() throws SQLException {
return flushStatements(false);
}
/**执行批量语句
* @param isRollBack 是否回滚
* @return 批处理结果
* @throws SQLException 异常
*/
public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
//调用doFlushStatements
return doFlushStatements(isRollBack);
}
/**执行带结果返回的查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param <E> 返回对象的泛型
* @return 对象列表
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//获取boundsql对象
BoundSql boundSql = ms.getBoundSql(parameter);
//创建缓存key对象
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
//调用query方法
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
/**执行带结果返回的查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param key 缓存key
* @param boundSql 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类型方法处理
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
//调用数据库查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
//todo 为何需要判断queryStack == 0, 不是应该一直为0吗
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
//清除一级缓存
clearLocalCache();
}
}
return list;
}
@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
//获取boundsql
BoundSql boundSql = ms.getBoundSql(parameter);
//调用doQueryCursor
return doQueryCursor(ms, parameter, rowBounds, boundSql);
}
/**延迟加载
* @param ms MappedStatement
* @param resultObject 元数据对象
* @param property 属性名
* @param key 缓存key
* @param targetType 对象类型
*/
@Override
public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
//todo
if (closed) {
throw new ExecutorException("Executor was closed.");
}
DeferredLoad deferredLoad = new DeferredLoad(resultObject, property, key, localCache, configuration, targetType);
if (deferredLoad.canLoad()) {
deferredLoad.load();
} else {
deferredLoads.add(new DeferredLoad(resultObject, property, key, localCache, configuration, targetType));
}
}
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
//创建一个cacheKey
CacheKey cacheKey = new CacheKey();
//使用mappedStatement的id,作为计算缓存key值的一部分
cacheKey.update(ms.getId());
//使用分页对象的offset,作为计算缓存key值的一部分
cacheKey.update(rowBounds.getOffset());
//使用分页对象的limit,作为计算缓存key值的一部分
cacheKey.update(rowBounds.getLimit());
//使用原始的sql语句,作为计算缓存key值的一部分
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
for (ParameterMapping parameterMapping : parameterMappings) {
//使用sql的输入参数,作为计算缓存key值的一部分
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
cacheKey.update(value);
}
}
//使用环境参数,作为计算缓存key值的一部分
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
/**当前CacheKey是否有对应的缓存
* @param ms MappedStatement
* @param key CacheKey
* @return 是否有对应的缓存
*/
@Override
public boolean isCached(MappedStatement ms, CacheKey key) {
//如果缓存中能命中,返回已经缓存
return localCache.getObject(key) != null;
}
/**提交事务
* @param required 是否需要
* @throws SQLException 异常
*/
@Override
public void commit(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException("Cannot commit, transaction is already closed");
}
//清除本地缓存
clearLocalCache();
//执行批处理语句
flushStatements();
//根据需要提交事务
if (required) {
transaction.commit();
}
}
/**回滚事务
* @param required 是否需求
* @throws SQLException 异常
*/
@Override
public void rollback(boolean required) throws SQLException {
if (!closed) {
try {
//清除本地缓存
clearLocalCache();
//执行批处理语句
flushStatements(true);
} finally {
//根据需要回滚事务
if (required) {
transaction.rollback();
}
}
}
}
/**
* 清除本地缓存
*/
@Override
public void clearLocalCache() {
if (!closed) {
//清除本地缓存
localCache.clear();
//清除输出参数缓存
localOutputParameterCache.clear();
}
}
/**执行update
* @param ms MappedStatement
* @param parameter 更新参数
* @return
* @throws SQLException
*/
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
/**执行批处理
* @param isRollback 是否需要回滚
* @return 批处理结果
* @throws SQLException 异常
*/
protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException;
/**执行query
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException;
/**执行游标查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)
throws SQLException;
/**关闭Statement
* @param statement
*/
protected void closeStatement(Statement statement) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// ignore
}
}
}
/**
* Apply a transaction timeout.
*
* @param statement
* a current statement
* @throws SQLException
* if a database access error occurs, this method is called on a closed <code>Statement</code>
* @since 3.4.0
* @see StatementUtil#applyTransactionTimeout(Statement, Integer, Integer)
*/
protected void applyTransactionTimeout(Statement statement) throws SQLException {
StatementUtil.applyTransactionTimeout(statement, statement.getQueryTimeout(), transaction.getTimeout());
}
/**处理本地缓存中的输出参数
* @param ms MappedStatement
* @param key 缓存key
* @param parameter 传入的参数对象
* @param boundSql boundsql
*/
private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {
//对callable类型的语句处理输出参数
if (ms.getStatementType() == StatementType.CALLABLE) {
//从输出参数的本地缓存中获取缓存
final Object cachedParameter = localOutputParameterCache.getObject(key);
if (cachedParameter != null && parameter != null) {
//如果传入的参数不为空,并且命中缓存
//创建一个被缓存对象的元数据对象
final MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);
//创建一个传入参数的的元数据对象
final MetaObject metaParameter = configuration.newMetaObject(parameter);
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
final String parameterName = parameterMapping.getProperty();
final Object cachedValue = metaCachedParameter.getValue(parameterName);
//给输入参数中的属性设置值
metaParameter.setValue(parameterName, cachedValue);
}
}
}
}
}
/**查询数据库
* @param ms MappedStatement
* @param parameter 传入的参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param key 缓存key
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
//todo 为何先放入一个站位对象
//在本地缓存中放入一个占位符对象
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
//调用doQuery
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
//从缓存中移除key
localCache.removeObject(key);
}
//将查询结果放入缓存
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
//如果是callable类型的调用,处理输出参数缓存
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
/**获取日志增强的连接
* @param statementLog log对象
* @return 增强后的连接
* @throws SQLException 异常
*/
protected Connection getConnection(Log statementLog) throws SQLException {
//从事务中获取连接对象
Connection connection = transaction.getConnection();
//如果开启了日志调试
if (statementLog.isDebugEnabled()) {
//构造一个使用ConnectionLogger动态代理的连接
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
/**设置Executor的包装Executor
* @param wrapper 包装的executor
*/
@Override
public void setExecutorWrapper(Executor wrapper) {
this.wrapper = wrapper;
}
private static class DeferredLoad {
private final MetaObject resultObject;
private final String property;
private final Class<?> targetType;
private final CacheKey key;
private final PerpetualCache localCache;
private final ObjectFactory objectFactory;
private final ResultExtractor resultExtractor;
// issue #781
public DeferredLoad(MetaObject resultObject,
String property,
CacheKey key,
PerpetualCache localCache,
Configuration configuration,
Class<?> targetType) {
this.resultObject = resultObject;
this.property = property;
this.key = key;
this.localCache = localCache;
this.objectFactory = configuration.getObjectFactory();
this.resultExtractor = new ResultExtractor(configuration, objectFactory);
this.targetType = targetType;
}
public boolean canLoad() {
return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER;
}
public void load() {
@SuppressWarnings("unchecked")
// we suppose we get back a List
List<Object> list = (List<Object>) localCache.getObject(key);
Object value = resultExtractor.extractObjectFromList(list, targetType);
resultObject.setValue(property, value);
}
}
从上述的几个核心方法中我们可以发现,BaseExecutor最终是通过子类实现doUpdate,doFlushStatements,doQuery,doQueryCursor的核心功能的.那我们就来研究下下面三个子类是如何实现的吧!
1.4 SimpleExecutor
doUpdate
/**执行更新
* @param ms MappedStatement
* @param parameter 更新参数
* @return 更新的条数
* @throws SQLException 异常
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
//获取配置对象
Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
//预处理statement,获取一个日志增强的statement
stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行更新
return handler.update(stmt);
} finally {
//关闭statement
closeStatement(stmt);
}
}
doQuery
/**执行query
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param boundSql 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();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//预处理statement,获取一个日志增强的statement
stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行查询
return handler.query(stmt, resultHandler);
} finally {
//关闭statement
closeStatement(stmt);
}
}
doQueryCursor
/**执行游标查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
//获取配置对象
Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
//预处理statement,获取一个日志增强的statement
Statement stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行查询
Cursor<E> cursor = handler.queryCursor(stmt);
//设置statement在完成时关闭
stmt.closeOnCompletion();
return cursor;
}
doFlushStatements
/**执行批处理
* @param isRollback 是否需要回滚
* @return 批处理结果
* @throws SQLException 异常
*/
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
//simpleExecutor不支持批量执行
//执行返回一个空集合
return Collections.emptyList();
}
prepareStatement
/**预处理statement
* @param handler StatementHandler
* @param statementLog statementLog
* @return 增强后的statement
* @throws SQLException 异常
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
//获取一个日志增强的connection
Connection connection = getConnection(statementLog);
//connection的增强类ConnectionLogger会在执行prepareStatement,prepareCall,createStatement
//方法时进行增强,并返回一个日志增强型Statement
//准备一个Statement
stmt = handler.prepare(connection, transaction.getTimeout());
//参数处理
handler.parameterize(stmt);
return stmt;
}
1.5 ReuseExecutor
doUpdate
/**执行update
* @param ms MappedStatement
* @param parameter 更新参数
* @return
* @throws SQLException
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
//获取配置对象
Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
//预处理statement,获取一个日志增强的statement, 并向statementMap中添加数据
Statement stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行更新
return handler.update(stmt);
}
doQuery
/**执行query
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param boundSql 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();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//预处理statement,获取一个日志增强的statement, 并向statementMap中添加数据
Statement stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行查询
return handler.query(stmt, resultHandler);
}
doQueryCursor
/**执行游标查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
//获取配置对象
Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
//预处理statement,获取一个日志增强的statement
Statement stmt = prepareStatement(handler, ms.getStatementLog());
//调用handler进行查询
return handler.queryCursor(stmt);
}
doFlushStatements
/**执行批处理
* @param isRollback 是否需要回滚
* @return 批处理结果
* @throws SQLException 异常
*/
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
//遍历map
for (Statement stmt : statementMap.values()) {
//关闭statement
closeStatement(stmt);
}
//清除map
statementMap.clear();
//reuseExecutor不支持批量执行
//返回空集合
return Collections.emptyList();
}
prepareStatement
/**预处理statement
* @param handler StatementHandler
* @param statementLog statementLog
* @return 增强后的statement
* @throws SQLException 异常
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
//获取sql语句
BoundSql boundSql = handler.getBoundSql();
String sql = boundSql.getSql();
if (hasStatementFor(sql)) {
//如果已经存在改语句的statement
//获取statement
stmt = getStatement(sql);
//设置超时时间
applyTransactionTimeout(stmt);
} else {
//获取一个日志增强的connection
Connection connection = getConnection(statementLog);
//connection的增强类ConnectionLogger会在执行prepareStatement,prepareCall,createStatement
//方法时进行增强,并返回一个日志增强型Statement
//准备一个Statement
stmt = handler.prepare(connection, transaction.getTimeout());
//放入map缓存
putStatement(sql, stmt);
}
//参数处理
handler.parameterize(stmt);
return stmt;
}
1.6 BatchExecutor
doUpdate
/**执行更新
* @param ms MappedStatement
* @param parameterObject 更新参数
* @return 更新的条数
* @throws SQLException 异常
*/
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
//获取配置对象
final Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
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)) {
//如果当前sql和当前sql,并且MappedStatement是当前MappedStatement
int last = statementList.size() - 1;
//获取最后一个statement
stmt = statementList.get(last);
//设置超时时间
applyTransactionTimeout(stmt);
//处理参数
handler.parameterize(stmt);// fix Issues 322
//从批处理结果列表中取出批处理结果对象
BatchResult batchResult = batchResultList.get(last);
//添加参数到批处理结果
batchResult.addParameterObject(parameterObject);
} else {
//获取一个日志增强的connection
Connection connection = getConnection(ms.getStatementLog());
//connection的增强类ConnectionLogger会在执行prepareStatement,prepareCall,createStatement
//方法时进行增强,并返回一个日志增强型Statement
//准备一个Statement
stmt = handler.prepare(connection, transaction.getTimeout());
//参数处理
handler.parameterize(stmt); // fix Issues 322
//设置当前sql
currentSql = sql;
//设置当前MappedStatement
currentStatement = ms;
//添加到statementList
statementList.add(stmt);
//添加批处理结果对象到batchResultList
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
//调用handler进行批量
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
doQuery
/**执行query
* @param ms MappedStatement
* @param parameterObject 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param boundSql 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();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
//获取一个日志增强的connection
Connection connection = getConnection(ms.getStatementLog());
//connection的增强类ConnectionLogger会在执行prepareStatement,prepareCall,createStatement
//方法时进行增强,并返回一个日志增强型Statement
//准备一个Statement
stmt = handler.prepare(connection, transaction.getTimeout());
//参数处理
handler.parameterize(stmt);
//调用handler进行查询
return handler.query(stmt, resultHandler);
} finally {
//关闭statement
closeStatement(stmt);
}
}
doQueryCursor
/**执行游标查询
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页对象
* @param boundSql boundSql
* @param <E> 结果对象泛型
* @return 结果
* @throws SQLException 异常
*/
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
//执行批处理
flushStatements();
//获取配置对象
Configuration configuration = ms.getConfiguration();
//构建一个RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
//获取一个日志增强的connection
Connection connection = getConnection(ms.getStatementLog());
//connection的增强类ConnectionLogger会在执行prepareStatement,prepareCall,createStatement
//方法时进行增强,并返回一个日志增强型Statement
//准备一个Statement
Statement stmt = handler.prepare(connection, transaction.getTimeout());
//参数处理
handler.parameterize(stmt);
//查询游标
Cursor<E> cursor = handler.queryCursor(stmt);
//设置statement在完成时关闭
stmt.closeOnCompletion();
return cursor;
}
doFlushStatements
/**执行批处理
* @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();
}
for (int i = 0, n = statementList.size(); i < n; i++) {
//遍历Statement列表
Statement stmt = statementList.get(i);
//设置超时时间
applyTransactionTimeout(stmt);
//获取配出来结果对象
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类型的keyGenerator
Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
//调用processBatch进行批处理中key的处理
jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141
//如果不是NoKeyGenerator
for (Object parameter : parameterObjects) {
//调用processAfter进行key的处理
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
// Close statement to close cursor #1109
//关闭statement
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) {
//关闭statement
closeStatement(stmt);
}
currentSql = null;
//清空statement集合
statementList.clear();
//清空批处理结果集合
batchResultList.clear();
}
}
1.7 总结
Executor的核心实现是通过StatementHandler完成的.ReuseExecutor和BatchExecutor的执行逻辑类似,只是分别多加了重用和批处理的逻辑.
2. StatementHandler
2.1 StatementHandler简介
通过上面Executor的学习我们知道了Executor是通过StatementHandler完成的,下面就来介绍一下StatementHandler
StatementHandler是一个接口,实现类有RoutingStatementHandler和BaseStatementHandler.其中BaseStatementHandler是一个抽象类,它的子类又有PreparedStatementHandler, CallableStatementHandler, SimpleStatementHandler.
2.2 RoutingStatementHandler
RoutingStatementHandler 内部维护了一个StatementHandler. 在构造函数中通过StatementType决定使用什么类型的StatementHandler
public class RoutingStatementHandler implements StatementHandler {
/**
* 实际处理Statement的代理对象
*/
private final StatementHandler delegate;
/**构造函数
* @param executor sql执行器
* @param ms MappedStatement
* @param parameter 参数
* @param rowBounds 分页信息
* @param resultHandler 结果处理器
* @param boundSql boundsql
*/
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//根据Statement类型,创建不同的代理处理器
switch (ms.getStatementType()) {
case STATEMENT:
//创建简单类型的处理器对象
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
//创建预处理型的处理器
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
//创建存储过程类型的处理器
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
/**预处理Statement
* @param connection 连接对象
* @param transactionTimeout 超时时间
* @return Statement
* @throws SQLException 异常
*/
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
//调用内部的代理进行预处理Statement
return delegate.prepare(connection, transactionTimeout);
}
/**参数化
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void parameterize(Statement statement) throws SQLException {
//调用内部的代理进行参数化处理
delegate.parameterize(statement);
}
/**批处理
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void batch(Statement statement) throws SQLException {
//调用内部的代理进行批处理
delegate.batch(statement);
}
/**更新
* @param statement statement
* @return 影响的行数
* @throws SQLException 异常
*/
@Override
public int update(Statement statement) throws SQLException {
//调用内部的代理进行更新
return delegate.update(statement);
}
/**查询
* @param statement statement
* @param resultHandler 结果处理器
* @param <E> 返回对象泛型
* @return 返回对象集合
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
//调用内部的代理进行查询
return delegate.query(statement, resultHandler);
}
/**查询游标
* @param statement statement
* @param <E> 返回对象泛型
* @return 返回游标
* @throws SQLException 异常
*/
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
//调用内部的代理进行游标查询
return delegate.queryCursor(statement);
}
/**获取BoundSql对象
* @return 返回BoundSql
*/
@Override
public BoundSql getBoundSql() {
//调用内部的代理进行获取BoundSql对象
return delegate.getBoundSql();
}
/**获取参数处理器
* @return 参数处理器对象
*/
@Override
public ParameterHandler getParameterHandler() {
//调用内部的代理进行获取参数处理器
return delegate.getParameterHandler();
}
}
Configuration中的newStatementHandler方法也是返回的一个RoutingStatementHandler
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
2.3 BaseStatementHandler
public abstract class BaseStatementHandler implements StatementHandler {
/**
* 核心配置对象
*/
protected final Configuration configuration;
/**
* 对象工厂,用于对象的创建和赋值
*/
protected final ObjectFactory objectFactory;
/**
* 类型处理器的注册器, 维护jdbcType和对应的处理器的关系
*/
protected final TypeHandlerRegistry typeHandlerRegistry;
/**
* 结果集处理器
*/
protected final ResultSetHandler resultSetHandler;
/**
* 参数处理器
*/
protected final ParameterHandler parameterHandler;
/**
* sql执行器
*/
protected final Executor executor;
/**
* MappedStatement
*/
protected final MappedStatement mappedStatement;
/**
* 分页对象
*/
protected final RowBounds rowBounds;
/**
* BoundSql
*/
protected BoundSql boundSql;
/**构造函数
* @param executor sql执行器
* @param mappedStatement mappedStatement
* @param parameterObject 参数
* @param rowBounds 分页对象
* @param resultHandler 结果处理器
* @param boundSql BoundSql
*/
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//设置属性值
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
//如果boundSql为空,先处理主键生成
generateKeys(parameterObject);
//从mappedStatement中获取boundSql
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
/**获取BoundSql对象
* @return 返回BoundSql
*/
@Override
public BoundSql getBoundSql() {
return boundSql;
}
/**获取参数处理器
* @return 参数处理器对象
*/
@Override
public ParameterHandler getParameterHandler() {
return parameterHandler;
}
/**预处理Statement
* @param connection 连接对象
* @param transactionTimeout 超时时间
* @return Statement
* @throws SQLException 异常
*/
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//实例化statement
statement = instantiateStatement(connection);
//设置超时时间
setStatementTimeout(statement, transactionTimeout);
//设置拉取数据的条数
setFetchSize(statement);
return statement;
} catch (SQLException e) {
//关闭statement
closeStatement(statement);
throw e;
} catch (Exception e) {
//关闭statement
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
/**实例化一个statement
* @param connection 数据库连接
* @return statement
* @throws SQLException 异常
*/
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
/**设置超时时间
* @param stmt stmt
* @param transactionTimeout 超时时间
* @throws SQLException 异常
*/
protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
Integer queryTimeout = null;
if (mappedStatement.getTimeout() != null) {
//获取mappedStatement的超时时间
queryTimeout = mappedStatement.getTimeout();
} else if (configuration.getDefaultStatementTimeout() != null) {
//获取默认的Statement的超时时间
queryTimeout = configuration.getDefaultStatementTimeout();
}
if (queryTimeout != null) {
//设置查询超时时间
stmt.setQueryTimeout(queryTimeout);
}
//比较transactionTimeout和queryTimeout,设置queryTimeout
StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
}
/**设置拉取条数
* @param stmt Statement
* @throws SQLException 异常
*/
protected void setFetchSize(Statement stmt) throws SQLException {
//获取mappedStatement中配置的fetchSize
Integer fetchSize = mappedStatement.getFetchSize();
if (fetchSize != null) {
//不为空时设置fetchSize
stmt.setFetchSize(fetchSize);
return;
}
//获取默认的拉取条数
Integer defaultFetchSize = configuration.getDefaultFetchSize();
if (defaultFetchSize != null) {
//不为空时设置fetchSzie
stmt.setFetchSize(defaultFetchSize);
}
}
/**关闭statement
* @param statement statement
*/
protected void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
//ignore
}
}
/**处理主键生成
* @param parameter sql参数
*/
protected void generateKeys(Object parameter) {
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
ErrorContext.instance().store();
//处理主键返回问题
keyGenerator.processBefore(executor, mappedStatement, null, parameter);
ErrorContext.instance().recall();
}
}
2.4 PreparedStatementHandler
public class PreparedStatementHandler extends BaseStatementHandler {
/**构造函数
* @param executor sql执行器
* @param mappedStatement mappedStatement
* @param parameter 参数
* @param rowBounds 分页参数
* @param resultHandler 结果处理器
* @param boundSql boundSql
*/
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//调用父类构造方法
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
/**更新
* @param statement statement
* @return 影响的行数
* @throws SQLException 异常
*/
@Override
public int update(Statement statement) throws SQLException {
//强转为PreparedStatement
PreparedStatement ps = (PreparedStatement) statement;
//执行sql
ps.execute();
//获取影响的行数
int rows = ps.getUpdateCount();
//获取参数
Object parameterObject = boundSql.getParameterObject();
//获取主键生成器
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
//后置处理主键
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
/**批处理
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void batch(Statement statement) throws SQLException {
//强转为PreparedStatement
PreparedStatement ps = (PreparedStatement) statement;
//加入到批处理
ps.addBatch();
}
/**查询
* @param statement statement
* @param resultHandler 结果处理器
* @param <E> 返回对象泛型
* @return 返回对象集合
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
//强转为PreparedStatement
PreparedStatement ps = (PreparedStatement) statement;
//执行sql
ps.execute();
//处理结果集并返回
return resultSetHandler.handleResultSets(ps);
}
/**查询游标
* @param statement statement
* @param <E> 返回对象泛型
* @return 返回游标
* @throws SQLException 异常
*/
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
//强转为PreparedStatement
PreparedStatement ps = (PreparedStatement) statement;
//执行sql
ps.execute();
//处理游标结果集并返回
return resultSetHandler.handleCursorResultSets(ps);
}
/**实例化一个statement
* @param connection 数据库连接
* @return statement
* @throws SQLException 异常
*/
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
//如果指定的keyGenerator为Jdbc3KeyGenerator
//获取指定主键的列表
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
//为指定主键列,使用自动生成的主键
//这里的prepareStatement方法会被代理增强, 增加日志功能
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
//使用指定主键列的方式预处理Statement
//这里的prepareStatement方法会被代理增强, 增加日志功能
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
//根据结果集类型,预编译statement
//这里的prepareStatement方法会被代理增强, 增加日志功能
return connection.prepareStatement(sql);
} else {
//根据结果集类型,预编译statement
//这里的prepareStatement方法会被代理增强, 增加日志功能
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
/**参数化
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void parameterize(Statement statement) throws SQLException {
//使用参数处理器处理参数
parameterHandler.setParameters((PreparedStatement) statement);
}
}
2.5 CallableStatementHandler
public class CallableStatementHandler extends BaseStatementHandler {
/**构造函数
* @param executor sql执行器
* @param mappedStatement mappedStatement
* @param parameter 参数
* @param rowBounds 分页参数
* @param resultHandler 结果处理器
* @param boundSql boundSql
*/
public CallableStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//调用父类构造函数
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
/**更新
* @param statement statement
* @return 影响的行数
* @throws SQLException 异常
*/
@Override
public int update(Statement statement) throws SQLException {
//强转成存储过程Statement
CallableStatement cs = (CallableStatement) statement;
//调用执行
cs.execute();
//获取影响的行数
int rows = cs.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
//后置处理主键返回
keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject);
//处理输出参数
resultSetHandler.handleOutputParameters(cs);
//返回影响的行数
return rows;
}
/**批处理
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void batch(Statement statement) throws SQLException {
//强转成存储过程Statement
CallableStatement cs = (CallableStatement) statement;
//加入批处理
cs.addBatch();
}
/**查询
* @param statement statement
* @param resultHandler 结果处理器
* @param <E> 返回对象泛型
* @return 返回对象集合
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
//强转成存储过程Statement
CallableStatement cs = (CallableStatement) statement;
//调用执行
cs.execute();
//处理结果集
List<E> resultList = resultSetHandler.handleResultSets(cs);
//处理输出参数
resultSetHandler.handleOutputParameters(cs);
//返回数据
return resultList;
}
/**查询游标
* @param statement statement
* @param <E> 返回对象泛型
* @return 返回游标
* @throws SQLException 异常
*/
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
CallableStatement cs = (CallableStatement) statement;
cs.execute();
Cursor<E> resultList = resultSetHandler.handleCursorResultSets(cs);
resultSetHandler.handleOutputParameters(cs);
return resultList;
}
/**实例化一个statement
* @param connection 数据库连接
* @return statement
* @throws SQLException 异常
*/
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
//获取sql语句
String sql = boundSql.getSql();
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
//如果是默认的结果集类型,调用prepareCall
return connection.prepareCall(sql);
} else {
//根据指定的结果集类型,调用prepareCall
return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
/**参数化
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void parameterize(Statement statement) throws SQLException {
//注册输出参数
registerOutputParameters((CallableStatement) statement);
//设置参数
parameterHandler.setParameters((CallableStatement) statement);
}
/**注册输出参数
* @param cs CallableStatement
* @throws SQLException 异常
*/
private void registerOutputParameters(CallableStatement cs) throws SQLException {
//获取参数映射对象
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
for (int i = 0, n = parameterMappings.size(); i < n; i++) {
//遍历
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
//处理OUT和INTOUT类型参数
if (null == parameterMapping.getJdbcType()) {
//输出参数必须指定jdbcType
throw new ExecutorException("The JDBC Type must be specified for output parameter. Parameter: " + parameterMapping.getProperty());
} else {
if (parameterMapping.getNumericScale() != null && (parameterMapping.getJdbcType() == JdbcType.NUMERIC || parameterMapping.getJdbcType() == JdbcType.DECIMAL)) {
//对数字类型和Decimal类型的属性,如果指定了精度
//注册有精度的参数
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getNumericScale());
} else {
if (parameterMapping.getJdbcTypeName() == null) {
//未指定jdbc名称
//注册参数
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE);
} else {
//注册参数
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getJdbcTypeName());
}
}
}
}
}
}
}
2.6 SimpleStatementHandler
public class SimpleStatementHandler extends BaseStatementHandler {
/**构造函数
* @param executor sql执行器
* @param mappedStatement mappedStatement
* @param parameter 参数
* @param rowBounds 分页参数
* @param resultHandler 结果处理器
* @param boundSql boundSql
*/
public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//调用父类构造函数
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
/**更新
* @param statement statement
* @return 影响的行数
* @throws SQLException 异常
*/
@Override
public int update(Statement statement) throws SQLException {
//获取sql
String sql = boundSql.getSql();
//参数对象
Object parameterObject = boundSql.getParameterObject();
//注解生成器
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
if (keyGenerator instanceof Jdbc3KeyGenerator) {
//执行sql,并且返回自动生成的主键
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
//获取影响的行数
rows = statement.getUpdateCount();
//后置处理主键
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
//执行sql
statement.execute(sql);
//获取影响的行数
rows = statement.getUpdateCount();
//后置处理主键
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else {
//不处理主键
//执行sql
statement.execute(sql);
//获取影响的行数
rows = statement.getUpdateCount();
}
//返回影响的行数
return rows;
}
/**批处理
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void batch(Statement statement) throws SQLException {
//获取sql语句
String sql = boundSql.getSql();
//加入到批处理
statement.addBatch(sql);
}
/**查询
* @param statement statement
* @param resultHandler 结果处理器
* @param <E> 返回对象泛型
* @return 返回对象集合
* @throws SQLException 异常
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
//获取sql
String sql = boundSql.getSql();
//执行sql
statement.execute(sql);
//处理结果集并返回
return resultSetHandler.handleResultSets(statement);
}
/**查询游标
* @param statement statement
* @param <E> 返回对象泛型
* @return 返回游标
* @throws SQLException 异常
*/
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
//获取sql
String sql = boundSql.getSql();
//执行sql
statement.execute(sql);
//处理游标结果集并返回
return resultSetHandler.handleCursorResultSets(statement);
}
/**实例化一个statement
* @param connection 数据库连接
* @return statement
* @throws SQLException 异常
*/
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
//创建statement
//这里的createStatement方法会被代理增强, 增加日志功能
return connection.createStatement();
} else {
//根据结果集类型,创建statement
//这里的createStatement方法会被代理增强, 增加日志功能
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
/**参数化
* @param statement statement
* @throws SQLException 异常
*/
@Override
public void parameterize(Statement statement) {
//简单类型的sql不支持参数处理
// N/A
}
}
2.7 总结
PreparedStatementHandler, CallableStatementHandler, SimpleStatementHandler 是在instantiateStatement()时通过构建不同类型的Statement进行核心的数据库操作的
总结
本章主要是介绍了Executor和StatementHandler. 也是mybatis封装数据库操作的最底层代码了.最终是依赖各种Statement实现各种数据库操作的,下一章一起学习查询后的数据自动封装的结果集.
喜欢的小伙伴请动动小手关注和点赞吧,也可留言一起探讨怎样更好的学习源码!!!
文章链接
Mybatis源码学习(一)初探执行流程
Mybatis源码学习(二)配置文件解析到SqlSessionFactory构建
Mybatis源码学习(三)SqlSession详解
Mybatis源码学习(四)自定义Mapper方法执行流程
Mybatis源码学习(五)Executor和StatementHandler详解
Mybatis源码学习(六)结果集自动封装机制
Mybatis源码学习(七)mybatis缓存详解
Mybatis源码学习(八)Mybatis设计模式总结
学习资料整理
本人作为Java开发菜鸡,平时也收集了很多学习视频,在此分享给大家一起学习
整套VIP学习视频
架构师相关视频
扫码领取
更多资料链接
Java免费学习视频下载
Python免费学习视频下载
Web前端免费学习视频下载
人工智能免费学习视频下载
大数据免费学习视频下载
UI设计免费学习视频下载