带有 spring 的 Mybatis ResultHandler 无法启动 运行

Mybatis ResultHandler with spring boot could not run

我有一个查询结果很大,所以我使用 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 启动自动为我创建一个 ObjRepository 实例,我在其他 class

中使用它
@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 启动应用程序时,它会卡在功能 consumeResult 中并且永远不会完成此功能。

我试图从 MyBatis 中查找文档,但一无所获。我配置错了吗?我正在为当前项目使用 PostgreSql

深​​入了解后,我发现了一些问题。

  • Return 类型必须是 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 的情况下实现相同的映射,但是当查询 returns 很多时它可能不是最佳解决方案行。

    @MapKey("id")
    @Results({@Result(), @Result(),...})
    @Select("SELECT .... FROM .... 
            JOIN .... JOIN ... WHERE country = #{country} ...")
    Map<Integer, MyObjDto> select(@Param('country') String country)
    
  • 在处理大量行时,使用 Cursor 可能会更有效率。详情请见documentation