Statementhandler是四大神器中最重要的一个对象,负责操作Statement与数据库进行交流.在工作时
还会使用ParameterHandler进行参数配置,使用ResultHandler将查询结果与实体类对象进行绑定
我们使用原生jdbc的时候会有statement相关的操作
Statement stmt = conn.createStatement();
StatementHandler的构成
源码如下
public interface StatementHandler {
Statement prepare(Connection var1, Integer var2) throws SQLException;
void parameterize(Statement var1) throws SQLException;
void batch(Statement var1) throws SQLException;
int update(Statement var1) throws SQLException;
<E> List<E> query(Statement var1, ResultHandler var2) throws SQLException;
<E> Cursor<E> queryCursor(Statement var1) throws SQLException;
BoundSql getBoundSql();
ParameterHandler getParameterHandler();
}
- prepare: 用于创建一个具体的 Statement 对象的实现类或者是 Statement 对象
- parametersize: 用于初始化 Statement 对象以及对sql的占位符进行赋值
- update: 用于通知 Statement 对象将 insert、update、delete 操作推送到数据库
- query: 用于通知 Statement 对象将 select 操作推送数据库并返回对应的查询结果
StatementHandler继承结构
image可以看出StatementHandler的继承体现和上一篇文章中的Executor的继承体系很类似
StatementHandler是顶级的接口,下面有两个直接实现类
-
RoutingStatementHandler:是一个具体实现类.在这个类中并没有对Statement对象进行具体使用.只是根据得到Executor类型,决定创建何种类型StatementHandler对象.在MyBatis工作时,使用的StatementHandler接口对象实际上就是RoutingStatementHandler对象.我们可以简单理解为
StatementHandler statmentHandler = new RountingStatementHandler();
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 根据 statementType 创建对应的 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()); } }
- BaseStatementHandler:是StatementHandler接口的另一个实现类.本身是一个抽象类.用于简化StatementHandler接口实现的难度,属于适配器设计模式体现.它有三个实现类.SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler.
在RountingStatementHandler创建时,就跟根据接收的Executor类型来创建这个三个类型对象的.- SimpleStatementHandler:管理Statement对象向数据库中推送不需要预编译的SQL语句
- PreparedStatementHandler:管理PreparedStatementHandler对象向数据库推送预编译的SQL语句
- CallableStatementHandler:管理CallableStatement对象调用数据库中构造函数
StatementHandler对象创建
StatementHandler对象是在SqlSession对象接收到操作命令时,由Configuraion中newStatementHandler方法负责调用的; Configuration 中的 newStatementHandler 是由执行器中的查询、更新方法来提供的,StatementHandler 其实就是由 Executor 负责管理和创建的
下面是SimpleExecutor中的update方法
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguration();
//创建StatementHandler,解析sql
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
stmt = this.prepareStatement(handler, ms.getStatementLog());
//handler解析sql
var6 = handler.update(stmt);
} finally {
this.closeStatement(stmt);
}
return var6;
}
image
由上图可以看出RoutingStatementHandler构造方法,将会根据Executor的类型决定创建SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler实例对象
StatementHandler接口方法
prepare
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(this.boundSql.getSql());
Statement statement = null;
try {
statement = this.instantiateStatement(connection);
this.setStatementTimeout(statement, transactionTimeout);
this.setFetchSize(statement);
return statement;
} catch (SQLException var5) {
this.closeStatement(statement);
throw var5;
} catch (Exception var6) {
this.closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + var6, var6);
}
}
prepare方法只在BaseStatementHandler被实现.在其三个子类中没有被重写.用于三个子类调用获得对应的Statement接口对象.
prepare方法依靠instantiateStatement(connection)方法来返回具体Statement接口对象.
这个方法是BaseStatementHandler中定义的抽象方法,由三个子类来具体实现.
protected abstract Statement instantiateStatement(Connection var1) throws SQLException;
SimpleStatementHandler中的instantiateStatement 方法
protected Statement instantiateStatement(Connection connection) throws SQLException {
return this.mappedStatement.getResultSetType() != null ? connection.createStatement(this.mappedStatement.getResultSetType().getValue(), 1007) : connection.createStatement();
}
PreparedStatementHandler中的instantiateStatement方法
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = this.boundSql.getSql();
if (this.mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = this.mappedStatement.getKeyColumns();
return keyColumnNames == null ? connection.prepareStatement(sql, 1) : connection.prepareStatement(sql, keyColumnNames);
} else {
return this.mappedStatement.getResultSetType() != null ? connection.prepareStatement(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareStatement(sql);
}
}
CallableStatementHandler中的instantiateStatement方法
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = this.boundSql.getSql();
return this.mappedStatement.getResultSetType() != null ? connection.prepareCall(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareCall(sql);
}
parameterize方法
主要为PreparedStatement和CallableStatement传参.因此只在PreparedStatementHandler和CallableStatementHandler中被重写PreparedStatementHandler中的parameterize
PreparedStatementHandler中的parameterize
public void parameterize(Statement statement) throws SQLException {
this.parameterHandler.setParameters((PreparedStatement)statement);
}
CallableStatementHandler中的parameterize
public void parameterize(Statement statement) throws SQLException {
this.registerOutputParameters((CallableStatement)statement);
this.parameterHandler.setParameters((CallableStatement)statement);
}
在这两个方法中,可以看到都是"ParameterHandler"对象进行参数赋值的
query方法
输送查询查询语句,并将查询结果转换对应的实体类对象
SimpleStatementHandler 中的 query 方法
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = this.boundSql.getSql();
statement.execute(sql);
return this.resultSetHandler.handleResultSets(statement);
}
PreparedStatementHandler中的query方法
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
return this.resultSetHandler.handleResultSets(ps);
}
可以看到在得到查询结果后,都是使用[ResultSetHandler]对结果进行转换
update
输送insert,update,delete语句并返回处理数据行
SimpleStatementHandler中的update方法
public int update(Statement statement) throws SQLException {
String sql = this.boundSql.getSql();
Object parameterObject = this.boundSql.getParameterObject();
KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
int rows;
if (keyGenerator instanceof Jdbc3KeyGenerator) {
statement.execute(sql, 1);
rows = statement.getUpdateCount();
keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
statement.execute(sql);
rows = statement.getUpdateCount();
keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject);
} else {
statement.execute(sql);
rows = statement.getUpdateCount();
}
return rows;
}
PreparedStatementHandler中update方法
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = this.boundSql.getParameterObject();
KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject);
return rows;
}
CallableStatementHandler中update方法
public int update(Statement statement) throws SQLException {
CallableStatement cs = (CallableStatement)statement;
cs.execute();
int rows = cs.getUpdateCount();
Object parameterObject = this.boundSql.getParameterObject();
KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
keyGenerator.processAfter(this.executor, this.mappedStatement, cs, parameterObject);
this.resultSetHandler.handleOutputParameters(cs);
return rows;
}
原文地址
网友评论