转载

MyBatis 的秘密(四)ResultSetHandler

ResultHandler

前面说过, StatmentHandler 最后在处理查询结果的时候,会调用 ResultSetHandler 处理结果,在看完 ResultSetHandler 之后,本来想分析一下它的代码,但是存在两个问题:

<association>

因此,便不一一分析其代码。这里,我们说一说 MyBatis 中的 ResultHandler

MyBatis Java API 中,对于 Select 可以指定一个 ResultHandler 来自行处理结果:

@Override
public void select(String statement, Object parameter, ResultHandler handler) {
  select(statement, parameter, RowBounds.DEFAULT, handler);
}

而对于 MyBatisMapper ,我们只需要在参数中添加 ResultHandlerMyBatis 便自己会使用该 ResultHandler 处理结果。

public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> resultContext);
}

ResultHandler 只有一个方法,处理结果,参数是 ResultContext

public interface ResultContext<T> {

//获取结果对象
T getResultObject();

//获取结果对象已经加载的数量
int getResultCount();

//是否已经停止加载
boolean isStopped();

//停止获取数据
void stop();

}

可以看到,通过 ResultContext ,我们可以定制化设置一些数据。

使用 ResultHandler 有以下两点限制:

  • 方法的返回值为 void ,因为通过定制的 ResultHandlerMyBaits 不会再后续继续处理数据
  • 方法的参数需要带有 ResultHander

以上限制从以下代码可以看出来:

case SELECT:
      //如果方法返回为空 并且 带有ResultHandler参数
      if (method.returnsVoid() && method.hasResultHandler()) {
        executeWithResultHandler(sqlSession, args);
        result = null;
      } else if (method.returnsMany()) {

而默认的 DefaultResultHandler 仅仅 是将结果放在 List 中,然后返回:

public class DefaultResultHandler implements ResultHandler<Object> {

private final List<Object> list;

public DefaultResultHandler() {
  list = new ArrayList<>();
}

@SuppressWarnings("unchecked")
public DefaultResultHandler(ObjectFactory objectFactory) {
  list = objectFactory.create(List.class);
}

@Override
public void handleResult(ResultContext<?> context) {
  list.add(context.getResultObject());
}

public List<Object> getResultList() {
  return list;
}
}

MyBatis 官网提示到,如果使用了 ResultHandler 处理结果,那么结果不会被缓存,这里需要注意。

明白了 ResultHandler ,就可以看 ResultSetHandler 了。

public interface ResultSetHandler {

//处理结果
<E> List<E> handleResultSets(Statement stmt) throws SQLException;

//处理游标结果  
<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

//处理存储过程返回的结果
void handleOutputParameters(CallableStatement cs) throws SQLException;

}

这个接口的所有方法都是输入 Statment ,输出处理完成的结果,其内部是调用的 statement#getResultSet() 实现。

需要明白的是,在调用此方法之前, MyBatis 已经执行了 Statment#Query() 方法。

总结一句话, ResultSetHandler 便是用来处理查询结果的, ResultHandler 是用来处理每行的结果。

原文  http://dengchengchao.com/?p=1194
正文到此结束
Loading...