介绍
StatementHandler 是四大组件中最重要的一个对象,一个 SQL 请求会经过会话,然后是执行器,最由 StatementHandler 执行 jdbc 最终到达数据库。
层次结构
SimpleStatementHandler
管理 Statement 对象并向数据库中推送不需要预编译的SQL语句。
PreparedStatementHandler
管理 Statement 对象并向数据中推送需要预编译的SQL语句。
CallableStatementHandler
管理 Statement 对象并调用数据库中的存储过程。
RoutingStatementHandler
在其构造函数中会根据 Mapper 文件中设置的 StatementType 来选择使用 SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler 作为内部的 delegate 对象。
PreparedStatementHandler 执行流程
预处理过程
当缓存都没有命中的情况下,BaseExecutor 会调用子类查询数据库的内容。
SimpleExecutor doQuery 方法
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 对象,里面 delegate 对象是 PreparedStatementHandler 类型
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter,
rowBounds, resultHandler, boundSql);
// JDBC4PreparedStatement 对象
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection);
handler.parameterize(stmt);
return stmt;
}
BaseStatementHandler prepare 方法
public Statement prepare(Connection connection) throws SQLException {
Statement statement = null;
// 创建 statement
statement = instantiateStatement(connection);
setStatementTimeout(statement);
setFetchSize(statement);
return statement;
}
PreparedStatementHandler instantiateStatement 方法
@Override
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);
}
}