存储映射结果是“查询结果”处理流程中的最后一环,实际上也是查询语句执行过程的最后一环。
映射结果存储逻辑
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。