You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDBI3 SqlObject Consumer使用Stream时如何修复“No Mapper Registered”错误?

修复SqlObject DAO流式处理结果集时的“No Mapper Registered”错误

问题描述

使用JDBI的SqlObject DAO进行流式结果处理时,已在DAO方法上添加@RegisterBeanMapper(IdTitle.class)注解,但调用时仍抛出错误:

No mapper registered for type java.util.stream.Stream<clarivate.mariadb.models.IdTitle>

对应的DAO方法代码:

@SqlQuery(" SELECT id, title FROM " + TABLE_XML_RECORDS //
    + " WHERE" //
    + "  issuedate IS NULL" //
    + "  AND sort_date <= :issueweek" //
    + "  AND sort_date >= :oldest" //
    + "  AND sort_date IS NOT NULL" //
    + " ORDER BY sort_date DESC")
@RegisterBeanMapper(IdTitle.class)
void getRecordIdsFor(@Bind("issueweek") LocalDate issueweek, @Bind("oldest") LocalDate oldestSortDate, Consumer<Stream<IdTitle>> consumer);

原因分析

根据JDBI官方文档中消费者参数的说明:

当消费者实现Consumer<Iterator>或Consumer<Stream>时,会使用包含结果的Iterator或Stream执行一次消费者,参数的静态类型决定映射行类型。

问题核心在于:JDBI需要明确识别Stream内部元素(IdTitle)的映射规则,但当前的@RegisterBeanMapper注解没有被正确关联到流的元素类型上,导致JDBI错误地尝试为Stream<IdTitle>本身寻找映射器,而非为IdTitle寻找。

解决方案

方案1:改用@MapResultAsBean注解

直接使用@MapResultAsBean替代@RegisterBeanMapper,该注解会直接将结果行映射为指定的Bean类,无需额外注册映射器,更适配流式场景:

@SqlQuery(" SELECT id, title FROM " + TABLE_XML_RECORDS //
    + " WHERE" //
    + "  issuedate IS NULL" //
    + "  AND sort_date <= :issueweek" //
    + "  AND sort_date >= :oldest" //
    + "  AND sort_date IS NOT NULL" //
    + " ORDER BY sort_date DESC")
@MapResultAsBean
void getRecordIdsFor(@Bind("issueweek") LocalDate issueweek, @Bind("oldest") LocalDate oldestSortDate, Consumer<Stream<IdTitle>> consumer);

方案2:显式指定映射器工厂

如果坚持使用@RegisterBeanMapper,可以通过指定映射器工厂,明确告知JDBI元素类型的映射规则:

@SqlQuery(" SELECT id, title FROM " + TABLE_XML_RECORDS //
    + " WHERE" //
    + "  issuedate IS NULL" //
    + "  AND sort_date <= :issueweek" //
    + "  AND sort_date >= :oldest" //
    + "  AND sort_date IS NOT NULL" //
    + " ORDER BY sort_date DESC")
@RegisterBeanMapper(value = IdTitle.class, factory = BeanMapperFactory.class)
void getRecordIdsFor(@Bind("issueweek") LocalDate issueweek, @Bind("oldest") LocalDate oldestSortDate, Consumer<Stream<IdTitle>> consumer);

方案3:全局注册映射器

如果多个DAO方法都需要使用IdTitle的映射,可在JDBI实例初始化时全局注册,避免每个方法重复添加注解:

Jdbi jdbi = Jdbi.create(dataSource);
jdbi.registerBeanMapper(IdTitle.class);

注意事项

  • 确保IdTitle类的字段名与SQL查询返回的列名一致,若列名与字段名不匹配,可使用@ColumnName注解进行映射
  • 流式处理时,JDBI会自动管理Stream的关闭,无需手动调用close()方法
  • 建议使用JDBI 3.x及以上版本,确保对Consumer<Stream<T>>的支持完整

内容的提问来源于stack exchange,提问作者Michael Conrad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:21:01