首页 > 解决方案 > 带有spring boot的Mybatis ResultHandler无法运行

问题描述

我有一个结果很大的查询,所以我使用 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

标签: javaspringpostgresqlspring-bootmybatis

解决方案


深入研究后,我发现了一些问题。

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

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

[1] 在不研究实施的@Results情况下,从技术上讲,支持是可能的。您应该在跟踪器上创建一个增强请求。


可能有用的附加信息。

  • 有一个方便的注释@MapKey可以在不使用的情况下实现相同的映射ResultHandler,但是当查询返回许多行时,它可能不是最佳解决方案。

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

推荐阅读