存储映射结果是“查询结果”处理流程中的最后一环,实际上也是查询语句执行过程的最后一环。

映射结果存储逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void storeObject(ResultHandler<?> resultHandler, 
DefaultResultContext<Object> resultContext,Object rowValue, ResultMapping
parentMapping, ResultSet rs) throws SQLException {
if (parentMapping != null) {
// 多结果集相关,不分析了
linkToParents(rs, parentMapping, rowValue);
} else {
// 存储结果
callResultHandler(resultHandler, resultContext, rowValue);
}
}

private void callResultHandler(ResultHandler<?> resultHandler,
DefaultResultContext<Object> resultContext, Object rowValue) {
// 设置结果到 resultContext 中
resultContext.nextResultObject(rowValue);
// 从 resultContext 获取结果,并存储到 resultHandler 中
((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}

将 rowValue 设置到 ResultContext 中,然后再将 ResultContext 对象作为参

数传给 ResultHandler 的 handleResult 方法。

ResultContext的实现类。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DefaultResultContext<T> implements ResultContext<T> {
private T resultObject;
private int resultCount;
/** 状态字段 */
private boolean stopped;
// 省略部分代码
@Override
public boolean isStopped() {
return stopped;
}
public void nextResultObject(T resultObject) {
resultCount++;
this.resultObject = resultObject;
}
@Override
public void stop() {
this.stopped = true;
}
}

DefaultResultContext 中包含了一个状态字段,表明结果上下文的状态。在处理多行数据

时,MyBatis 会检查该字段的值,已决定是否需要进行后续的处理。

ResultHandler的实现类,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DefaultResultHandler implements ResultHandler<Object> {
private final List<Object> list;

public DefaultResultHandler() {
list = new ArrayList<Object>();
}
@Override
public void handleResult(ResultContext<? extends Object> context) {
// 添加结果到 list 中
list.add(context.getResultObject());
}
public List<Object> getResultList() {
return list;
}
}

DefaultResultHandler 默认使用 List 存储结果。除此之外,如果 Mapper(或 Dao)

接口方法返回值为 Map 类型,此时则需要另一种 ResultHandler 实现类处理结果,即

DefaultMapResultHandler。