JOOQ 3.15嵌套映射时报Cannot convert row to model错误如何解决?
错误产生原因
- 映射目标类型不兼容:你最终使用的
ATableRecord.class是jOOQ根据a_table生成的内置表记录类,它的字段结构和a_table的数据库列严格一一对应,不包含你额外查询的自定义c字段(你已经将其转换为CDomain类型)。jOOQ做映射时发现结果集中存在无法匹配到ATableRecord字段的CDomain类型值,尝试进行强制类型转换失败,因此抛出异常。 - 代码结构存在语法错误:你提供的代码括号位置错位,在
where条件后多闭合了一个括号,相当于把整段查询语句当成了一个Field对象调用as("a").convertFrom(...),而非对查询返回的结果记录做转换,直接导致类型处理逻辑不符合预期。 - ROW表达式空值处理逻辑偏差:当左连接没有匹配到
c_table的记录时,jOOQ的row()构造的表达式不会返回null,只会返回内部所有字段均为null的Row记录,你直接调用r.into(CDomain.class)会生成一个所有属性为null的CDomain实例,而非null,进一步加剧了后续映射时的类型不匹配问题。
你看到的“反向转换”现象,本质是ATableRecord期望接收的所有字段都是对应数据库表的原生类型,jOOQ发现有一个不识别的CDomain类型值,尝试将其转换为Record类型塞到ATableRecord的对应位置,因此出现了反过来转的错误。
修复方案
- 首先自定义接收结果的POJO,不要使用jOOQ生成的
ATableRecord:
// 自定义POJO包含a_table的所有属性和嵌套的CDomain属性 public class ADomain { private UUID id; private CDomain c; // 补充无参构造函数、getter、setter } public class CDomain { private LocalDateTime dateStarted; private LocalDateTime dateCompleted; // 补充无参构造函数、getter、setter }
- 修正查询代码的结构,调整转换逻辑:
// aId、bId为入参 var result = select( A_TABLE.asterisk(), row( C_TABLE.STARTED_DATE.as("dateStarted"), C_TABLE.COMPLETED_DATE.as("dateCompleted") ).as("c").convertFrom(r -> // 左连接无匹配时直接返回null,避免生成全空属性的CDomain实例 r.get(0) == null ? null : r.into(CDomain.class) ) ).from(A_TABLE) .leftOuterJoin(C_TABLE) .on(C_TABLE.A_ID.eq(A_TABLE.ID).and(C_TABLE.B_ID.eq(bId))) .where(A_TABLE.ID.eq(aId)) // 直接映射到自定义的ADomain类 .fetchOneInto(ADomain.class);
如果你确实需要使用ATableRecord,可以拆分查询逻辑,先单独查询a_table的记录获取ATableRecord,再单独查询关联的c_table字段做转换,不要将额外的自定义字段放到查询ATableRecord的字段列表中。
内容的提问来源于stack exchange,提问作者dougalg
相关产品推荐
相关产品推荐

