Mybatis 源码之数据库结果集

普通结果集

定位: org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

处理配置 resultMap, resultSet 和 resultSets 的结果映射(支持多个结果集)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@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;
// 获取第一个 ResultSet 对象
ResultSetWrapper rsw = getFirstResultSet(stmt);

// 获取 MappedStatement.resultMaps 集合
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
// 如果集合集不为空,则 resultMaps 集合不能为空,否则抛出异常
validateResultMapsCount(rsw, resultMapCount);
// 遍历 resultMaps 集合
while (rsw != null && resultMapCount > resultSetCount) {
// 获取该结果集对应的 ResultMap 对象
ResultMap resultMap = resultMaps.get(resultSetCount);
// 根据 ResultMap 中定义的映射规则对 ResultSet 进行映射,并将映射的结果对象添加到multipleResult 集合中保存
handleResultSet(rsw, resultMap, multipleResults, null);
// 获取下一个结果集
rsw = getNextResultSet(stmt);
// 清空 nestedResultObjects 集合
cleanUpAfterHandlingResultSet();
// 递增 resultSetCount
resultSetCount++;
}

// 获取 MappedStatement.resultSets 属性,该属性对多结果集的情况使用,该属性将列出语句执行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的,
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
// 根据 resultSet 的名称,获取未处理的 ResultMapping
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
// 根据 ResultMap 对象映射结果集
handleResultSet(rsw, resultMap, null, parentMapping);
}
// 获取下一个结果集
rsw = getNextResultSet(stmt);
// 清空 nestedResultObjects 集合
cleanUpAfterHandlingResultSet();
// 递增 resultSetCount
resultSetCount++;
}
}

return collapseSingleResultList(multipleResults);
}

定位: org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

处理单个结果集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 处理结果集
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
// 处理多结果集中的嵌套映射
handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
} else {
if (resultHandler == null) {
// 如果用户未指定处理映射结果对象的 ResultHandler 对象,则使用 DefaultResultHandler 作为默认的 ResultHandler 对象
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 对 ResultSet 进行映射,并将映射得到的结果对象添加到 DefaultResultHandler 对象中暂存
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
// 将 DefaultResultHandler 中保存的结果对象添加到 multipleResults 集合中
multipleResults.add(defaultResultHandler.getResultList());
} else {
// 使用用户指定的 ResultHandler 对象处理结果对象
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
} finally {
// issue #228 (close resultsets)
// 调用 ResultSet.close 方法关闭结果集
closeResultSet(rsw.getResultSet());
}
}
// 处理一行的所有字段值
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 针对存在嵌套 ResultMap 的情况
if (resultMap.hasNestedResultMaps()) {
// 检测是否允许在嵌套映射中使用 RowBound
ensureNoRowBounds();
checkResultHandler();
// 检测是否允许在嵌套映射中使用用户自定义的 ResultHandler
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
// 针对不含嵌套映射的简单映射的处理
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}

非嵌套结果集

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap
遍历结果集的所有行, 将一行的数据自动映射成一个对象,并将此对象添加到 resultList 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
// 默认上下文对象
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
ResultSet resultSet = rsw.getResultSet();
// 根据 RowBounds 中的 offset 定位到指定的记录
skipRows(resultSet, rowBounds);
// 检测已经处理的行数是否已经达到上限(RowBounds,limit)以及ResultSet中是否还有可处理的记录
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
// 根据该行记录以及 ResultMap.discriminator,决定映射使用的 ResultMap
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
// 根据最终确定的 ResultMap 对 ResultSet 中的该行记录进行映射,得到映射后的结果对象
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
// 将映射创建的结果对象添加到 ResultHandler.resultList 中保存
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}


org.apache.ibatis.executor.resultset.DefaultResultSetHandler#resolveDiscriminatedResultMap

使用配置字段的结果值来决定使用哪个 resultMap

1
2
3
4
<!-- 配置 -->
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
// 记录已经处理过的 ResultMap 的 id
Set<String> pastDiscriminators = new HashSet<>();
// 获取 ResultMap 中的 Discriminator 对象
Discriminator discriminator = resultMap.getDiscriminator();
while (discriminator != null) {
// 获取记录中对应列的值,其中会使用相应的 TypeHandler 对象将该列值转换成 Java 类型
final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
// 根据该列值获取对应的 ResultMap 的 id
final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
if (configuration.hasResultMap(discriminatedMapId)) {
// 根据上述获取的 id 查找相应的 ResultMap 对象
resultMap = configuration.getResultMap(discriminatedMapId);
// 记录当前 Discriminator 对象
Discriminator lastDiscriminator = discriminator;
// 获取 ResultMap 对象中的 Discrimination
discriminator = resultMap.getDiscriminator();
// 检测 Discriminator 是否出现了环形引用
if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
break;
}
} else {
break;
}
}
// 该 ResultMap 对象为映射最终使用的 ResultMap
return resultMap;
}

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue
创建实体类对象;自动映射结果集中有的column,但 resultMap 中并没有配置;根据 resultMap 节点中配置的映射关系进行映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  // 核心,取得一行的值
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
// 实例化 ResultLoaderMap (延迟加载器)
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建该行记录映射之后得到的结果对象,该结果对象的类型由 ResultMap 节点的 type 属性指定
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
// 创建上述结果对象相应的 MetaObject 对象
final MetaObject metaObject = configuration.newMetaObject(rowValue);
// 成功映射任意属性,则 foundValues 为 true,否则 foundValues 为 false
boolean foundValues = this.useConstructorMappings;
// 检测是否需要进行自动映射
if (shouldApplyAutomaticMappings(resultMap, false)) {
// 自动映射 ResultMap 中未明确指定的列
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
// 映射 ResultMap 中明确指定需要映射的列
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
// 如果没有成功映射任何属性,则根据 mybatis-config.xml 中的 returnInstanceForEmptyRow 配置决定返回空的结果对象还是返回 null
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
// 自动映射
// 如果配置了自动映射, 跟根据 typeHandler 来解析列
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
// 获取 ResultSet 中存在,但 ResultMap 中没有明确映射的列所对应的UnMappedColumnAutoMapping 集合,如果 ResultMap 中设置的 resultType 为 HashMap 的话,则全部的列都会在这里获取到
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
// 遍历 autoMapping 集合
for (UnMappedColumnAutoMapping mapping : autoMapping) {
// 使用 TypeHandler 获取自动映射的列值
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
// gcode issue #377, call setter on nulls (value is not 'found')
// 将自动映射的属性值设置到结果对象中
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
}
// 根据 <resultMap> 节点中配置的映射关系进行映射
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
throws SQLException {
// 获取该 ResultMap 中明确需要进行映射的列名集合
final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
boolean foundValues = false;
// 获取 ResultMap.propertyResultMappings 集合,其中记录了映射使用的所有 ResultMapping 对象
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
// 处理列前缀
String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
if (propertyMapping.getNestedResultMapId() != null) {
// the user added a column attribute to a nested result map, ignore it
// 该属性需要使用一个嵌套 ResultMap 进行映射,忽略 column 属性
column = null;
}
// 下面的逻辑主要处理三种场景
// 场景1:column是{prop1=col1,prop2=col2}这种形式的,一般与嵌套查询配合使用,表示将col1和col2的列值传递给内层嵌套查询作为参数
// 场景2:基本类型的属性映射
// 场景3:多结果集的场景处理,该属性来自于另一个结果集
if (propertyMapping.isCompositeResult() // 场景1
|| (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) // 场景2
|| propertyMapping.getResultSet() != null) { // 场景3
// 通过 getPropertyMappingValue 方法完成映射,并得到属性值
Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
// issue #541 make property optional
// 获取属性名称
final String property = propertyMapping.getProperty();
if (property == null) {
continue;
} else if (value == DEFERRED) {
// DEFERRED表示的是占位符对象
foundValues = true;
continue;
}
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {
// gcode issue #377, call setter on nulls (value is not 'found')
// 设置属性值
metaObject.setValue(property, value);
}
}
}
return foundValues;
}
// 嵌套查询, 加载出此字段的值; 多结果集: 直接返回占位符; 否则根据 typeHandler 来解析返回值
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
throws SQLException {
// 嵌套查询
if (propertyMapping.getNestedQueryId() != null) {
return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
// 多结果集的处理
} else if (propertyMapping.getResultSet() != null) {
addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK?
// 返回占位符对象
return DEFERRED;
} else {
// 获取 ResultMapping 中记录的 TypeHandler 对象
final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
// 使用 TypeHandler 对象获取属性值
return typeHandler.getResult(rs, column);
}
}

org.apache.ibatis.reflection.MetaObject

元对象, 各种get,set方法类似ognl表达式的解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// MetaObject 的构造方法是 private 修饰的,只能通过 forObject 这个静态方法创建 MetaObject 对象
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
// 若 object 为 null ,则统一返回 SystemMetaObject.NULL_META_OBJECT
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
// 初始化上述字段
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;

if (object instanceof ObjectWrapper) {
// 如果对象本身已经是 ObjectWrapper 型,则直接赋给 objectWrapper
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
// 若 ObjectWrapperFactory 能够为该原始对象创建对应的 ObjectWrapper 对象,则优先使用ObjectWrapperFactory,而
// DefaultObjectWrapperFactory.hasWrapperFor 始终返回 false,用户可以自定义ObjectWrapperFactory 实现进行扩展
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
// 若原始对象为 map 对象,则创建 MapWrapper 对象
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
// 若原始对象是 Collection 类型,则创建 CollectionWrapper 对象
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
// 若原始对象是普通的 javaBean 对象,则创建 BeanWrapper 对象
this.objectWrapper = new BeanWrapper(this, object);
}
}
public Object getValue(String name) {
// 解析属性表达式
PropertyTokenizer prop = new PropertyTokenizer(name);
// 处理子表达式
if (prop.hasNext()) {
// 根据 PropertyTokenizer 解析后制定的属性,创建相应的 MetaObject 对象
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
// 如果上层就是 null 了,那就结束,返回 null
return null;
} else {
// 递归处理子表达式
return metaValue.getValue(prop.getChildren());
}
} else {
// 通过 ObjectWrapper 获取指定的属性值
return objectWrapper.get(prop);
}
}

// 设置值
public void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null) {
// 如果上层就是 null了,还得看有没有儿子,没有那就结束
// don't instantiate child path if value is null
return;
} else {
// 否则还得 new 一个,委派给 ObjectWrapper.instantiatePropertyValue
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
// 递归调用 setValue
metaValue.setValue(prop.getChildren(), value);
} else {
// 到了最后一层了,所以委派给ObjectWrapper.set
objectWrapper.set(prop, value);
}
}

嵌套结果集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 创建 DefaultResultContext 对象
final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
ResultSet resultSet = rsw.getResultSet();
// 定位到指定的记录行
skipRows(resultSet, rowBounds);
Object rowValue = previousRowValue;
// 检测是否能继续映射结果集中剩余的记录行
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
// 通过 resolveDiscriminatedResultMap 方法决定映射使用的 ResultMap 对象
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
// 为该行记录生成 CacheKey
final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
// 根据 CacheKey 查找 nestedResultObjects 集合
Object partialObject = nestedResultObjects.get(rowKey);
// issue #577 && #542
// 检测 resultOrdered 属性
if (mappedStatement.isResultOrdered()) {
// 主结果对象发生变化
if (partialObject == null && rowValue != null) {
// 清空 nestedResultObjects 集合
nestedResultObjects.clear();
// 调用 storeObject 方法保存主结果对象
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
// 完成该行记录的映射返回结果对象,将结果对象添加到 nestedResultObjects 集合中
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
} else {
// 完成该行记录的映射返回结果对象,将结果对象添加到 nestedResultObjects 集合中
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
// 调用 storeObject 方法保存结果对象
if (partialObject == null) {
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}
// 对 resultOrdered 属性为 true 时的特殊处理,调用 storeObject 方法保存结果对象
if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
previousRowValue = null;
} else if (rowValue != null) {
previousRowValue = rowValue;
}
}

游标结果集

定位: org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleCursorResultSets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling cursor results").object(mappedStatement.getId());

// 获取结果集并封装成 ResultSetWrapper 对象
ResultSetWrapper rsw = getFirstResultSet(stmt);

// 获取映射使用的 ResultMap 对象集合
List<ResultMap> resultMaps = mappedStatement.getResultMaps();

// 边界检测,只能映射一个结果集,所以只能存在一个 ResultMap 对象
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
if (resultMapCount != 1) {
throw new ExecutorException("Cursor results cannot be mapped to multiple resultMaps");
}
// 使用第一个 ResultMap 对象
ResultMap resultMap = resultMaps.get(0);
// 将 ResultSetWrapper 对象、映射使用的 ResultMap 对象一级控制映射的起止位置的 RowBounds 对象封装成 DefaultCursor 对象
return new DefaultCursor<>(this, resultMap, rsw, rowBounds);
}

默认游标

定位: org.apache.ibatis.cursor.defaults.DefaultCursor

在调用游标迭代器的 hasNext 或者 next 方法时,会将 ResultSet 中的列封装成实体对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
protected T fetchNextUsingRowBound() {
// 映射一行数据库记录,得到结果对象
T result = fetchNextObjectFromDatabase();
// 从结果集开始一条条记录映射,但是将RowBounds.offset之前的映射结果全部忽略
while (objectWrapperResultHandler.fetched && indexWithRowBound < rowBounds.getOffset()) {
result = fetchNextObjectFromDatabase();
}
return result;
}

protected T fetchNextObjectFromDatabase() {
// 检测当前右表对象是否关闭
if (isClosed()) {
return null;
}

try {
objectWrapperResultHandler.fetched = false;
// 更新游标状态
status = CursorStatus.OPEN;
if (!rsw.getResultSet().isClosed()) {
// 通过DefaultResultSetHandler.handleRowValues方法完成映射,
resultSetHandler.handleRowValues(rsw, resultMap, objectWrapperResultHandler, RowBounds.DEFAULT, null);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}

// 获取结果对象
T next = objectWrapperResultHandler.result;
if (objectWrapperResultHandler.fetched) {
// 统计返回的结果对象数量
indexWithRowBound++;
}
// No more object or limit reached
// 检测是否还存在需要映射的记录,如果没有,则关闭游标并修改状态
if (!objectWrapperResultHandler.fetched || getReadItemsCount() == rowBounds.getOffset() + rowBounds.getLimit()) {
// 关闭结果集以及对应的Statement对象
close();
status = CursorStatus.CONSUMED;
}
objectWrapperResultHandler.result = null;

// 返回结果对象
return next;
}
// org.apache.ibatis.cursor.defaults.DefaultCursor$CursorIterator
protected class CursorIterator implements Iterator<T> {
T object;
int iteratorIndex = -1;
public boolean hasNext() {
if (!objectWrapperResultHandler.fetched) {
object = fetchNextUsingRowBound();
}
return objectWrapperResultHandler.fetched;
}
public T next() {
// Fill next with object fetched from hasNext()
// 在 hasNext 方法也会调用 fetchNextUsingRowBound 方法,并将映射结果对象记录到 object 字段中
T next = object;
if (!objectWrapperResultHandler.fetched) {
// 对结果集进行映射的核心
next = fetchNextUsingRowBound();
}
if (objectWrapperResultHandler.fetched) {
objectWrapperResultHandler.fetched = false;
object = null;
// 记录返回结果对象的个数
iteratorIndex++;
return next;
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove element from Cursor");
}
}

存储过程输出参数

定位: org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleOutputParameters

将存储过程中 OUT 参数结果设置到调用方的参数列表对象中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Override
public void handleOutputParameters(CallableStatement cs) throws SQLException {
// 获取用户传入的实际参数,并为其创建相应的MetaObject对象
final Object parameterObject = parameterHandler.getParameterObject();
final MetaObject metaParam = configuration.newMetaObject(parameterObject);
// 获取 BoundSql.parameterMappings 集合,其中记录了参数相关信息
final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
// 遍历所有参数信息
for (int i = 0; i < parameterMappings.size(); i++) {
final ParameterMapping parameterMapping = parameterMappings.get(i);
// 只处理 OUT|INOUT
if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
// 如果存在输出类型的参数,则解析参数值,并设置到 parameterObject 中
if (ResultSet.class.equals(parameterMapping.getJavaType())) {
// 如果指定该输出参数为 ResultSet 类型,则需要进行映射
handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);
} else {
// 使用 TypeHandler 获取参数值,并设置到 parameterObject 中
final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();
metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));
}
}
}
}

// 处理游标(OUT参数)
private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException {
if (rs == null) {
return;
}
try {
// 获取映射使用的 ResultMap 对象
final String resultMapId = parameterMapping.getResultMapId();
final ResultMap resultMap = configuration.getResultMap(resultMapId);
// 将结果集封装成 ResultSetWrapper
final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);
if (this.resultHandler == null) {
// 创建用于保存映射结果对象的 DefaultResultHandler 对象
final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory);
// 通过 handleRowValues 方法完成映射操作,并将结果对象保存到 DefaultResultHandler 中
handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
// 将映射得到的结果对象保存到 parameterObject 中
metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());
} else {
handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
}
} finally {
// issue #228 (close resultsets)
closeResultSet(rs);
}
}