mybatis StatementHandler
是四大神器中最重要的一个对象。
主要负责:Statement,PrepareStatement,CallableStatement创建工作。
同时负责:PrepareStatement,CallableStatement输送Sql的语句的占位符,使用ParameterHandler进行参数配置。
操作对象的运行行为update,select等。
public interface StatementHandler {
//创建Statement,PrepareStatement,CallableStatement
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
//参数初始化,针对PrepareStatement,CallableStatement关联预编译Sql语句中占位符进行修改
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 getBoundSql();
ParameterHandler getParameterHandler();
}
StatementHandler继承关系
- BaseStatementHandler
负责实现prepare方法 - RoutingStatementHandler
三种Handler使用的调度器 - SimpleStatementHandler
Statement对象初始化 - PreparedStatementHandler
预编译对象PreparedStatement进行初始化 - CallableStatementHandler
CallableStatement
StatementHandler核心方法
StatementHandler对象是在SqlSession对象接收到操作命令时,由Configuraion中newStatementHandler方法负责调用.
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//RoutingStatementHandler,三种Handler使用的调度器。
//根据传入的SQL语句返回SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
RoutingStatementHandler调度器代码,根据MappedStatement返回某种类型的StatementHandler。
怎么判断返回那种类型的Handler:取决于sql语句,没有占位符就是SimpleStatementHandler。有占位符的出现PreparedStatementHandler。call {} CallableStatementHandler。非人为控制
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
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());
}
}
返回某种类型的StatementHandler,构造方法中都调用了父类的构造方法
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);
}
通过以上的调用便生成了相应的Handler,后续Statement的创建工作便会在相应的handler中完成。(在BaseStatementHandler中prepare方法中调用了instantiateStatement抽象方法,该方法由子类实现。)
prepare方法实在执行器中调用的
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//重点方法,该方法是个抽象的方法,实现在子类中实现
statement = instantiateStatement(connection);
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);
}
}
abstract Statement instantiateStatement(Connection connection) throws SQLException;
SimpleStatementHandler中instantiateStatement方法的实现,调用connection.createStatement()
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() != null) {
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.createStatement();
}
}
PreparedStatementHandler中instantiateStatement方法的实现,调用connection.prepareStatement()生成,
@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);
}
}
以上便完成了statement的创建。
前文提到其同时负责:PrepareStatement,CallableStatement输送Sql的语句的占位符。
使用ParameterHandler进行参数配置,方法为parameterize。其中调用了四大神器的ParameterHandler进行参数配置
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
操作对象的运行行为update,query。
int update(Statement statement)
throws SQLException;
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
在BaseStatementHandler各个子类中重写了该方法
调用了PreparedStatement ps = (PreparedStatement) statement;ps.execute();
调用了四大神器的resultSetHandler进行结果配置
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
本文地址:https://blog.csdn.net/wsdfym/article/details/107592986
上一篇: 李智慧 - 架构师训练营总览
下一篇: JS变量赋值
推荐阅读
-
SpringBoot + Mybatis 增删改查实例教程详细解读
-
IntelliJ IDEA中使用mybatis-generator的示例
-
使用maven整合Spring+SpringMVC+Mybatis框架详细步骤(图文)
-
SpringMVC+Spring+Mybatis实现支付宝支付功能的示例代码
-
spring+springmvc+mybatis+maven入门实战(超详细教程)
-
mybatis输入映射和输出映射实例详解
-
mybatis防止SQL注入的方法实例详解
-
Mybatis实现分页的注意点
-
Java使用MyBatis框架分页的5种方式
-
springboot+springmvc+mybatis项目整合