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
相关产品推荐
相关产品推荐

