这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战
时序图
sequenceDiagram
participant C as SimpleExecutor
participant A as PreparedStatementHandler
participant B as DefaultResultSetHandler
C ->> A : query
A ->> B : handleResultSets
B ->> B : handleResultSet
B ->> B : handleRowValues
B ->> B : handleRowValuesForSimpleResultMap
B ->> B : getRowValue
B ->> B : applyPropertyMappings
B -->> C : List<Object>
详细步骤
PreparedStatementHandler#query
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行SQL
ps.execute();
// 结果集处理
return resultSetHandler.handleResultSets(ps);
}
DefaultResultSetHandler#handleResultSets
/**
* 处理statement得到的多结果集(也可能是单结果集,这是多结果集的一种简化形式),最终得到结果列表
*
* handleResultSets 方法完成了对多结果集的处理。但是对于每一个结果集的处理是由handleResultSet子方法实现的
* @param stmt Statement语句
* @return 结果列表
* @throws SQLException
*/
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
// 用以存储处理结果的列表
final List<Object> multipleResults = new ArrayList<>();
// 可能会有多个结果集,该变量用来对结果集进行计数
int resultSetCount = 0;
// 可能会有多个结果集,先取出第一个结果集
ResultSetWrapper rsw = getFirstResultSet(stmt);
// 查询语句对应的resultMap节点,可能含有多个
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
// 合法性校验(存在输出结果集的情况下,resultMapCount不能为0)
validateResultMapsCount(rsw, resultMapCount);
// 循环遍历每一个设置了resultMap的结果集
while (rsw != null && resultMapCount > resultSetCount) {
// 获得当前结果集对应的ResultMap
ResultMap resultMap = resultMaps.get(resultSetCount);
// 进行结果集的处理
handleResultSet(rsw, resultMap, multipleResults, null);
// 获取下一结果集
rsw = getNextResultSet(stmt);
// 清理上一条结果集的环境
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
// 获取多结果集中所有结果集的名称
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
// 循环遍历每一个设置resultMap的结果集
while (rsw != null && resultSetCount < resultSets.length) {
// 获取该结果集对应的父级resultMap中的resultMapping(注:resultMapping用来描述对象属性的映射关系)
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
// 获取被嵌套的resultMap编号
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
// 处理嵌套映射
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
// 判断是否为单结果集:如果是,则返回结果列表;如果不是则返回结果集列表
return collapseSingleResultList(multipleResults);
}
DefaultResultSetHandler#handleResultSet
/**
* 处理单一的结果集
* @param rsw ResultSet 的包装
* @param resultMap resultMap节点信息
* @param multipleResults 用来存储处理结果的列表
* @param parentMapping
* @throws SQLException
*/
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) { // 嵌套的结果
// 向子方法闯入parentMapping。处理结果中的记录
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else { // 非嵌套的结果
if (resultHandler == null) {
// defaultResultHandler 能够将结果对象聚合成一个列表返回
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 处理结果中的记录
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
// 添加处理后的结果
multipleResults.add(defaultResultHandler.getResultList());
} else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
closeResultSet(rsw.getResultSet());
}
}
DefaultResultSetHandler#handleRowValuesForSimpleResultMap
/**
* 处理非嵌套映射的结果
* @param rsw 结果集包装
* @param resultMap 结果映射
* @param resultHandler 结果处理器
* @param rowBounds 翻页限制条件
* @param parentMapping 父级结果映射
* @throws SQLException
*/
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
// 当前要处理的结果集
ResultSet resultSet = rsw.getResultSet();
// 根据翻页配置,跳过指定的行
skipRows(resultSet, rowBounds);
// 持续处理下一条结果,判断条件为;还有结果需要处理 && 结果集没有关闭 && 还有下一条结果
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
// 经过鉴别器鉴别,确定经过鉴别器分析的最终要使用resultMap
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
// 拿到一行记录,并且将其转化为一个对象
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
// 把这一行记录转化出的对象存起来
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
DefaultResultSetHandler#getRowValue
- 解析ResultMap标签时,会将属性的TypeHandler确定下来,见Mybatis源码之resultMap标签解析
/**
* 将一条记录转化为一个对象
* @param rsw 结果集包装
* @param resultMap 结果映射
* @param columnPrefix 列前缀
* @return 转化得到的对象
* @throws SQLException
*/
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建这一行记录对应的空对象
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
// 根据对象得到其MetaObject
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
// 是否允许自动映射未明示的字段
if (shouldApplyAutomaticMappings(resultMap, false)) {
// 自动映射未明示的字段(resultType),映射时的TypeHandler通过属性名与set方法参数类型的映射来获取属性的类型,并据此获取对应的TypeHandler
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
// 按照明示的字段进行重新映射(resultMap),解析XML时获取TypeHandler
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
以上便是Mybatis中ResultSet结果集处理流程。