mybatis-StatementHandler解析
概述
StatementHandler,Statement处理器,主要是和jdbc中的Statement交互。
public interface StatementHandler {
/**
* 创建Statement
* @param connection
* @param transactionTimeout
* @return
* @throws SQLException
*/
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
/**
* 设置参数到statement
* @param statement
* @throws SQLException
*/
void parameterize(Statement statement)
throws SQLException;
/**
* 批量支持
* @param 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 getBoundSql();
ParameterHandler getParameterHandler();
}
提供的能力:
- 创建Statement实例
- 设置参数
- 执行sql
类图结构:
看这个结构和Executor是不是特别像。
BaseStatementHandler依旧是通用逻辑处理(异常处理、通用参数设置)
SimpleStatementHandler:普通Statement处理器。
PreparedStatementHandler:PrepareStatement处理器。
CallableStatementHandler:CallableStatement处理器。
RoutingStatementHandler:封装路由逻辑。
BaseStatementHandler
基础Statement处理器
protected final Configuration configuration;
/**
* 对象工厂,用于创建返回值类型实例
*/
protected final ObjectFactory objectFactory;
protected final TypeHandlerRegistry typeHandlerRegistry;
/**
* 数据集处理器
*/
protected final ResultSetHandler resultSetHandler;
/**
* 参数处理器
*/
protected final ParameterHandler parameterHandler;
// 执行器
protected final Executor executor;
// 映射Statement
protected final MappedStatement mappedStatement;
// 分页参数
protected final RowBounds rowBounds;
// 动态sql
protected 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
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
StatementHandler 在构造函数中会创建ParameterHandler和ResultSetHandler用于参数和返回值的处理。
prepare
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
/*
* 对应创建三种Statement,对应StatementType
* simple
* prepare
* callable(用来调用存储过程)
*/
statement = instantiateStatement(connection);
// statement通用参数设置
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
实例化Statement实例由子类实现,超时时间、fetch大小通用设置。
SimpleStatementHandler
instantiateStatement
实例化Statement,
@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);
}
}
通过Connection创建普通Statement。
update
@Override
public int update(Statement statement) throws SQLException {
String sql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
// 主键获取处理
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 {
// 执行sql 返回值
statement.execute(sql);
rows = statement.getUpdateCount();
}
return rows;
}
更新方法,增加了对主键的处理。
query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
// 返回值处理
return resultSetHandler.handleResultSets(statement);
}
直接执行,结果值处理交给ResultHandler。
PreparedStatementHandler
对应PrepareStatement
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() == ResultSetType.DEFAULT) {
return connection.prepareStatement(sql);
} else {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
其实也只是通过Connection创建PrepareStatement
update
@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;
}
逻辑比较简单,执行sql后,主键生成器执行。
query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
和Simple一样。
CallableStatementHandler(存储过程略过)
RoutingStatementHandler
路由Statement处理器
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
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());
}
}
可以看出RoutingStatementHandler其实就是在构造函数内封装了路由的逻辑,将这个switch case包装了起来,实际的实现还是委托给实际实现类完成。一个不错的小设计,可以借鉴一下。
总结
StatementHandler主要是封装了和JDBC-Statement的实例化,设置参数和返回值转换在ParameterHandler和ResultSetHandler。层层拆分,职责清晰。
本文地址:https://blog.csdn.net/qq_28695733/article/details/107198818