Mybatis源码(五)
6、SimpleExecutor.doQuery()
1)创建StatementHandler
在 configuration.newStatementHandler()中,new一个newStatementHandler,先得到RoutingStatementHandler。
RoutingStatementHandler里面没有任何的实现,使用来创建基本的StatementHandler的。这里会根据MappedStatement里面的getStatementType
决定StatementHandler的类型。默认是PREPARED(STATEMENT、PREPARED、CALLABLE)
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
// 创建 StatementHandler 的时候做了什么? >>
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里面包含了处理参数的ParameterHandler和处理结果集的ResultSetHandler。
这两个对象创建:
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject,
RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
....
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds,
parameterHandler, resultHandler, boundSql);
}
这三个对象都可以被插件拦截的,所以在创建之后都要用拦截器进行包装方法。
// 植入插件逻辑(返回代理对象)
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
四大对象包装创建完成。
QA:上面是三个对象,还有一个对象?是在什么时候创建的?(Executor)
- 创建Statement
用new出来的statementHandler创建statement对象。
如果有插件包装,会先走到被拦截的业务逻辑,SimpleExecutor对象
// 获取一个 Statement对象
stmt = prepareStatement(handler, ms.getStatementLog());
prepareStatement方法对语句执行,处理参数:
// 执行查询
handler.query(stmt, resultHandler);
这里会调用parameterHandler设置参数,如果有插件包装,会先走到被拦截的业务逻辑。
@Override
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
执行StatementHandler的query方法。
RoutingStatementHandler的query()方法。
delegate委派,最终执行PreparedStatementHandler的query()方法。
4)执行PreparedStatement的execute方法
// 到了JDBC的流程
ps.execute();
后面就是JDBC的PreparedStatement的执行了。
5)resultSetHandler处理结果集
如果有插件包装,会先走到被拦截的业务逻辑。
// 处理结果集
return resultSetHandler.handleResultSets(ps);
QA:怎么把ResultSet转换成List<Object>的呢?
resultSetHandler只有一个实现类:DefaultResultSetHandler。也就是执行了DefaultResultSetHandler的handleResultSets()方法。
首先我们会先拿到第一个结果集,如果没有配置一个查询返回多个结果集的情况,一般只有一个结果集。如果下面的这个while循环我们不使用,
就是执行一次。
然后调用handleResultSet()方法。
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
...
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
...
if (parentMapping != null) {
...
handleResultSet(rsw, resultMap, null, parentMapping);
}
}
调用代理方法,执行SQL
image