Statementhandler是四大神器中最重要的一個(gè)對象,負(fù)責(zé)操作Statement與數(shù)據(jù)庫進(jìn)行交流.在工作時(shí)
還會(huì)使用ParameterHandler進(jìn)行參數(shù)配置,使用ResultHandler將查詢結(jié)果與實(shí)體類對象進(jìn)行綁定
我們使用原生jdbc的時(shí)候會(huì)有statement相關(guān)的操作
Statement stmt = conn.createStatement();
StatementHandler的構(gòu)成
源碼如下
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: 用于創(chuàng)建一個(gè)具體的 Statement 對象的實(shí)現(xiàn)類或者是 Statement 對象
- parametersize: 用于初始化 Statement 對象以及對sql的占位符進(jìn)行賦值
- update: 用于通知 Statement 對象將 insert、update、delete 操作推送到數(shù)據(jù)庫
- query: 用于通知 Statement 對象將 select 操作推送數(shù)據(jù)庫并返回對應(yīng)的查詢結(jié)果
StatementHandler繼承結(jié)構(gòu)

可以看出StatementHandler的繼承體現(xiàn)和上一篇文章中的Executor的繼承體系很類似
StatementHandler是頂級(jí)的接口,下面有兩個(gè)直接實(shí)現(xiàn)類
-
RoutingStatementHandler:是一個(gè)具體實(shí)現(xiàn)類.在這個(gè)類中并沒有對Statement對象進(jìn)行具體使用.只是根據(jù)得到Executor類型,決定創(chuàng)建何種類型StatementHandler對象.在MyBatis工作時(shí),使用的StatementHandler接口對象實(shí)際上就是RoutingStatementHandler對象.我們可以簡單理解為
StatementHandler statmentHandler = new RountingStatementHandler();public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 根據(jù) statementType 創(chuàng)建對應(yīng)的 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接口的另一個(gè)實(shí)現(xiàn)類.本身是一個(gè)抽象類.用于簡化StatementHandler接口實(shí)現(xiàn)的難度,屬于適配器設(shè)計(jì)模式體現(xiàn).它有三個(gè)實(shí)現(xiàn)類.SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler.
在RountingStatementHandler創(chuàng)建時(shí),就跟根據(jù)接收的Executor類型來創(chuàng)建這個(gè)三個(gè)類型對象的.- SimpleStatementHandler:管理Statement對象向數(shù)據(jù)庫中推送不需要預(yù)編譯的SQL語句
- PreparedStatementHandler:管理PreparedStatementHandler對象向數(shù)據(jù)庫推送預(yù)編譯的SQL語句
- CallableStatementHandler:管理CallableStatement對象調(diào)用數(shù)據(jù)庫中構(gòu)造函數(shù)
StatementHandler對象創(chuàng)建
StatementHandler對象是在SqlSession對象接收到操作命令時(shí),由Configuraion中newStatementHandler方法負(fù)責(zé)調(diào)用的; Configuration 中的 newStatementHandler 是由執(zhí)行器中的查詢、更新方法來提供的,StatementHandler 其實(shí)就是由 Executor 負(fù)責(zé)管理和創(chuàng)建的
下面是SimpleExecutor中的update方法
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguration();
//創(chuàng)建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;
}

由上圖可以看出RoutingStatementHandler構(gòu)造方法,將會(huì)根據(jù)Executor的類型決定創(chuàng)建SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler實(shí)例對象
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被實(shí)現(xiàn).在其三個(gè)子類中沒有被重寫.用于三個(gè)子類調(diào)用獲得對應(yīng)的Statement接口對象.
prepare方法依靠instantiateStatement(connection)方法來返回具體Statement接口對象.
這個(gè)方法是BaseStatementHandler中定義的抽象方法,由三個(gè)子類來具體實(shí)現(xiàn).
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);
}
在這兩個(gè)方法中,可以看到都是"ParameterHandler"對象進(jìn)行參數(shù)賦值的
query方法
輸送查詢查詢語句,并將查詢結(jié)果轉(zhuǎn)換對應(yīng)的實(shí)體類對象
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);
}
可以看到在得到查詢結(jié)果后,都是使用[ResultSetHandler]對結(jié)果進(jìn)行轉(zhuǎn)換
update
輸送insert,update,delete語句并返回處理數(shù)據(jù)行
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;
}
原文地址