
本文介绍如何在 jooq 中通过 `row2.mapping()` 对关联查询的子字段(如外键关联的父表字段)进行类型安全、简洁的嵌套对象映射,避免手动构造 record 或冗余转换逻辑。
在使用 JOOQ 进行多表关联查询时,若希望将子查询结果(例如 child 表中关联的 parent 字段)直接映射为嵌套 Java 对象(如 ParentDTO),无需借助 convert() 或复杂自定义 Converter,而是应充分利用 JOOQ 提供的类型化 Row 映射能力。
核心思路是:利用 DSL.row(...) 构造一个强类型的 Row2
以下为完整可运行示例(基于你提供的表结构):
// 假设已生成 JOOQ 代码:CHILD, PARENT 表对象可用
record ChildDTO(Long id, String name, ParentDTO parent) {}
record ParentDTO(Long id, String name) {}
List result = dslContext
.select(
CHILD.ID,
CHILD.NAME,
row(CHILD.parent().ID, CHILD.parent().NAME) // ← 返回 Row2
.mapping(ParentDTO::new) // ← 类型安全映射为 ParentDTO
)
.from(CHILD)
.fetch(Records.mapping(ChildDTO::new)); // 主对象映射(自动匹配字段顺序) ✅ 关键要点说明:
- CHILD.parent().ID 是 JOOQ 自动生成的外键导航路径(需确保 child.parent_id 正确关联至 parent.id,且代码生成器启用了 relations 支持);
- row(...).mapping(...) 返回的是 SelectField
,可直接作为 SELECT 子句一部分,无需包裹 DSL.field(...); - Records.mapping(ChildDTO::new) 要求构造函数参数顺序与 select(...) 中字段顺序严格一致(即 id, name, parent);
- 此方式完全类型安全、零反射、无运行时异常风险,且编译期即可校验字段数量与类型匹配性。
⚠️ 注意事项:
- 若未启用外键关系推导(如 generateRelations = true),CHILD.parent() 可能不可用,此时可改用显式 join + 别名字段:
.select(CHILD.ID, CHILD.NAME, row(PARENT.ID, PARENT.NAME).mapping(ParentDTO::new)) .from(CHILD) .join(PARENT).on(CHILD.PARENT_ID.eq(PARENT.ID))
- RowN.mapping() 仅适用于固定字段数(如 Row2, Row3),动态列场景需改用 RecordMapper 或 ad-hoc converter。
综上,Row.mapping() 是 JOOQ 中实现轻量级嵌套对象映射最简洁、推荐的方式——它兼顾表达力、类型安全与性能,是替代传统 Converter 和手动 Record.into(...) 的现代实践。










