Executor的执行步骤:https://blog.csdn.net/lichunericli/article/details/82563667
在Executor的执行步骤中可看出executor.query()方法的最终执行通常是通过SimpleExecutor的doQuery()方法来实现的:
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
// Executor通过StatementHandler的prepare()方法来预编译SQL语句
StatementHandler handler =
configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 由Statement可看出其底层是通过JDBC来实现的
Statement stmt = prepareStatement(handler, ms.getStatementLog());
// Sql的执行处理和结果的封装执行返回都在query中实现
handler.<E>query(stmt, resultHandler);
closeStatement(stmt); // 注意内存的溢出,Statement需要在finally中关闭
}
由doQuery源码可以看出StatementHandler的相关处理是在此处实现的。
1. StatementHandler会话处理器生成
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object
parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = // 根据Executor的类型路由,获取对应的StatementHandler类型
new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); // 注意拦截器对底层的影响
return statementHandler;
}
2. StatementHandler的初始化
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Connection connection = getConnection(statementLog); // 通过Transaction获取数据库连接
// 调用StatementHandler里的prepare方法预编译SQL语句并设置相关Statement参数
Statement stmt = handler.prepare(connection, transaction.getTimeout());
// SQL参数的设置,通过ParameterHandler来实现
handler.parameterize(stmt);
return stmt;
}
备注:预编译SQL语句是通过PreparedStatementHandler中的instantiateStatement()方法实现的
3. 预编译SQL语句和Statement参数初始化
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
// Statement的初始化
Statement statement = instantiateStatement(connection);
// Statement的相关参数设置
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
closeStatement(statement); // 注意Statement的关闭
return statement;
}
// PreparedStatementHandler中实现的Statement的初始化
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql(); // 数据库主键生成策略的设置
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(),
ResultSet.CONCUR_READ_ONLY);
} else {
return connection.prepareStatement(sql);
}
}
总结:Statement的作用是和数据库进行会话,Executor先调用它的prepare方法预编译SQL语句并设置Statement参数,然后再用ParameterHandler来设置SQL参数以完成预编译,最后通过StatementHandler执行对应的操作,由ResultHandler处理返回结果。