StatementHandler
Statement 处理器 的顶级接口,里面接口不算多。
/**
* Statement 处理器 的顶级接口
* @author Clinton Begin
*/
public interface StatementHandler {
// 准备操作,创建Statement对象
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
// 初始化Statement参数
void parameterize(Statement statement)
throws SQLException;
// 批处理操作
void batch(Statement statement)
throws SQLException;
// 写操作
int update(Statement statement)
throws SQLException;
// 读操作
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
// 执行读操作返回 游标
<E> Cursor<E> queryCursor(Statement statement)
throws SQLException;
// 返回boundSql对象
BoundSql getBoundSql();
// 返回参数相关的Statement对象
ParameterHandler getParameterHandler();
}
实现类
其主要的实现类图
主要的实现类
- BaseStatementHandler:StatementHandler 基类,提供骨架方法
- CallableStatementHandler:存储过程使用的方法
- PreparedStatementHandler:第一次执行sql语句时会进行预编译,在接下来执行相同的SQL语句时会提高数据库性能
- RoutingStatementHandler:负责将不同的 Statement 类型,路由到上述三个实现类上
- SimpleStatementHandler:这里简单的sql语句是指sql语句中没有变量,不会通过外部进行参数传入的sql语句
BaseStatementHandler
StatementHandler 基类,提供骨架方法
public abstract class BaseStatementHandler implements StatementHandler {
// 配置
protected final Configuration configuration;
// 类工厂
protected final ObjectFactory objectFactory;
// 类型处理注册表
protected final TypeHandlerRegistry typeHandlerRegistry;
// 结果处理器
protected final ResultSetHandler resultSetHandler;
// 参数处理器
protected final ParameterHandler parameterHandler;
// 执行器
protected final Executor executor;
protected final MappedStatement mappedStatement;
protected final RowBounds rowBounds;
protected BoundSql boundSql;
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 获得 Configuration 对象
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
// 获得 TypeHandlerRegistry 和 ObjectFactory 对象
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
// 如果 boundSql 为空,一般是写类操作,
// 例如:insert、update、delete ,则先获得自增主键,然后再创建 BoundSql 对象
if (boundSql == null) { // issue #435, get the key before calculating the statement
// 获得自增主键
generateKeys(parameterObject);
// 创建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);
}
@Override
public BoundSql getBoundSql() {
return boundSql;
}
@Override
public ParameterHandler getParameterHandler() {
return parameterHandler;
}
// 主准备处理
@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);
}
}
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
Integer queryTimeout = null;
// 获得mappedStatement的超时设置
if (mappedStatement.getTimeout() != null) {
queryTimeout = mappedStatement.getTimeout();
} else if (configuration.getDefaultStatementTimeout() != null) {
// 使用默认的超时设置
queryTimeout = configuration.getDefaultStatementTimeout();
}
// 设置查询超时
if (queryTimeout != null) {
stmt.setQueryTimeout(queryTimeout);
}
// 设置事务
StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
}
protected void setFetchSize(Statement stmt) throws SQLException {
// 获得设置的fetchSize,并设置进Statement中,
// 如果不存在,则使用默认配置
Integer fetchSize = mappedStatement.getFetchSize();
if (fetchSize != null) {
stmt.setFetchSize(fetchSize);
return;
}
Integer defaultFetchSize = configuration.getDefaultFetchSize();
if (defaultFetchSize != null) {
stmt.setFetchSize(defaultFetchSize);
}
}
protected void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
//ignore
}
}
protected void generateKeys(Object parameter) {
// 获得KeyGenerator对象
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
ErrorContext.instance().store();
// 前置处理,创建自增编号到 parameter 中
keyGenerator.processBefore(executor, mappedStatement, null, parameter);
ErrorContext.instance().recall();
}
}
主要实现了基础数据的构造,和一些骨架方法,statement的方法instantiateStatement被交给子类实现
CallableStatementHandler
存储过程使用的方法
SimpleStatementHandler
这里简单的sql语句是指sql语句中没有变量,不会通过外部进行参数传入的sql语句
/**
* 继承 BaseStatementHandler 抽象类,java.sql.Statement 的 StatementHandler 实现类
* 这里简单的sql语句是指sql语句中没有变量,不会通过外部进行参数传入的sql语句。
* @author Clinton Begin
*/
public class SimpleStatementHandler extends BaseStatementHandler {
public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
@Override
public int update(Statement statement) throws SQLException {
// 获得SQL
String sql = boundSql.getSql();
// 获得参数和KeyGenerator对象
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
// 根据不同的KeyGenerator类型配置不同的execute参数
// 假如不属于Jdbc3KeyGenerator和SelectKeyGenerator
// 则不进行keyGenerator.processAfter操作
if (keyGenerator instanceof Jdbc3KeyGenerator) {
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
statement.execute(sql);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else {
statement.execute(sql);
rows = statement.getUpdateCount();
}
// 影响的数量
return rows;
}
// 执行匹处理语句
@Override
public void batch(Statement statement) throws SQLException {
String sql = boundSql.getSql();
statement.addBatch(sql);
}
// 执行查询,然后处理结果
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.handleResultSets(statement);
}
// 执行查询,然后处理结果
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.handleCursorResultSets(statement);
}
// 创建一个Statement 假如ResultSetType不为默认类型,则使用设置的类型
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
return connection.createStatement();
} else {
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
// SimpleStatementHandler 不存在基本的参数变量
@Override
public void parameterize(Statement statement) {
// N/A
}
}
update
@Override
public int update(Statement statement) throws SQLException {
// 获得SQL
String sql = boundSql.getSql();
// 获得参数和KeyGenerator对象
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
// 根据不同的KeyGenerator类型配置不同的execute参数
// 假如不属于Jdbc3KeyGenerator和SelectKeyGenerator
// 则不进行keyGenerator.processAfter操作
if (keyGenerator instanceof Jdbc3KeyGenerator) {
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
statement.execute(sql);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else {
statement.execute(sql);
rows = statement.getUpdateCount();
}
// 影响的数量
return rows;
}
从boundSql,mappedStatement中获得对应的参数后,通过statement.execute进行执行操作,同时根据主键生成策略,判断是否需要对入参进行处理
instantiateStatement
// 创建一个Statement 假如ResultSetType不为默认类型,则使用设置的类型
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
return connection.createStatement();
} else {
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
初始化一个statement
parameterize
// SimpleStatementHandler 不存在基本的参数变量
@Override
public void parameterize(Statement statement) {
// N/A
}
因为不存在参数替换,所以此方法置空。
PreparedStatementHandler
第一次执行sql语句时会进行预编译,在接下来执行相同的SQL语句时会提高数据库性能
update
// 和SimpleStatementHandler 不同没有进行KeyGenerator操作
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
和SimpleStatementHandler不同的是statement会被强转成PreparedStatement
instantiateStatement
// 创建Statement
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
// 处理 Jdbc3KeyGenerator 的情况
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() == ResultSetType.DEFAULT) {
return connection.prepareStatement(sql);
} else {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
使用connection.prepareStatement而不是connection.createStatement生成Statement
parameterize
@Override
public void parameterize(Statement statement) throws SQLException {
// 设置参数的占位符
parameterHandler.setParameters((PreparedStatement) statement);
}
使用parameterHandler来处理参数绑定的问题的。
而parameterHandler的创建在BaseStatementHandler中
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
// 获得 Configuration 对象
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
// 获得 TypeHandlerRegistry 和 ObjectFactory 对象
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
// 如果 boundSql 为空,一般是写类操作,
// 例如:insert、update、delete ,则先获得自增主键,然后再创建 BoundSql 对象
if (boundSql == null) { // issue #435, get the key before calculating the statement
// 获得自增主键
generateKeys(parameterObject);
// 创建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);
}
而关于这个ParameterHandler我们会在下一篇说明
RoutingStatementHandler
负责将不同的 Statement 类型,路由到上述三个实现类上,它其实是个代理类,在构造的时候根据条件,构造出一个符合条件的StatementHandler,然后具体执行方法都是用的构造出来的StatementHandler。
// org/apache/ibatis/executor/statement/RoutingStatementHandler.java
// StatementHandler的代理
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
// 将不同的 Statement 类型,路由到上述三个实现类上
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());
}
}
最终实现逻辑的是delegate.
总结
可以看出来除了CallableStatementHandler,之外主要工作的两个类是SimpleStatementHandler,PreparedStatementHandler。两者区别
- 前者无需进行参数处理,后者需要
- 前者创建Statement使用的是connection.createStatement()后者使用的是connection.prepareStatement
- 两者对数据库的访问都是使用Statement的相关操作