前面说过, 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); }
而对于 MyBatis
的 Mapper
,我们只需要在参数中添加 ResultHandler
, MyBatis
便自己会使用该 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
,因为通过定制的 ResultHandler
, MyBaits
不会再后续继续处理数据 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
是用来处理每行的结果。