我有一个查询,查询结果很大,因此我使用ResultHandler跟踪MyBatis的文档来处理结果

因为我只想将所有结果放入Map中,所以ResultHandler可以为我提供帮助。

@Mapper
Interface ObjRepository {
  @Result(value = {....})
  @Select("SELECT .... FROM ....
          JOIN .... JOIN ... WHERE country = #{country} ...")
  Void consumeResult(@Parram('country') String country, ResultHanlder<MyObjDto> handle)
}


Spring Boot会自动为我创建一个ObjRepository实例,并在其他类中使用它

@Sfl4j
@Service
public class MyService {
  private Map<Long, MyObjDto> map = new HashMap();

  @Autowired ObjRepository objRepository;

  @PostConstruct
  public init() {
    Log.info("start loading");
    objReposity.consumeResult("US", dto -> map.put(dto.getId(), dto));
    Log.info("finish");
  }

}


我的问题是,当我启动Spring Boot应用程序时,它将停留在功能consumeResult中,并且永远无法完成此功能。

我试图从MyBatis中找到文档,但什么也没找到。我配置错了吗?我正在为当前项目使用PostgreSql

最佳答案

经过更深入的研究,我发现了一些问题。


返回类型必须为void而不是Void
该语句必须具有@ResultMap@ResultType。似乎不支持@Result,[1]。
传递给ResultHandler#handleResult()的参数是ResultContext,因此您需要调用getResultObject()来获取DTO。

objReposity.consumeResult("US", resultContext -> {
  MyObjDto dto = resultContext.getResultObject();
  map.put(dto.getId(), dto);
});



[1]在不考虑实现的情况下,在技术上可能支持@Results。您应该在tracker上创建一个增强请求。



可能有用的附加信息。


方便的注释@MapKey无需使用ResultHandler即可实现相同的映射,但是当查询返回许多行时,它可能不是最佳解决方案。

@MapKey("id")
@Results({@Result(), @Result(),...})
@Select("SELECT .... FROM ....
        JOIN .... JOIN ... WHERE country = #{country} ...")
Map<Integer, MyObjDto> select(@Param('country') String country)

处理大量行时,使用Cursor可能更有效。有关详细信息,请参见documentation

07-27 13:17