如何用Jooq将子表查询关联的父表行转换为Java Record
解决jOOQ查询多对一关系并映射到嵌套Java Record的问题
问题回顾
你有两张多对一关系的表:
CREATE TABLE parent ( id BIGINT PRIMARY KEY, name VARCHAR(255) ) CREATE TABLE child ( id BIGINT PRIMARY KEY, name VARCHAR(255), parent_id BIGINT FOREIGN KEY REFERENCES parent (id) )
希望查询child表时,将关联的parent行自动转换为Java Record,之前的代码存在关联方向错误,且未正确使用转换方法。
正确实现方案
1. 先定义对应的Java Record
假设你需要以下两个Record类:
public record Parent(Long id, String name) {} public record ChildDTO(Long id, String name, Parent parent) {}
2. 方案一:使用嵌套的Records.mapping(最简洁推荐)
jOOQ的Records.mapping支持直接嵌套构造函数映射,无需手动处理行转换:
var result = dslContext.select( CHILD.ID, CHILD.NAME, PARENT.ID, PARENT.NAME ) .from(CHILD) // 正确关联方向:从Child关联对应的Parent .join(PARENT).on(CHILD.PARENT_ID.eq(PARENT.ID)) // 嵌套映射:先构造Parent实例,再传入ChildDTO构造函数 .fetch(Records.mapping(ChildDTO::new, Parent::new));
这里jOOQ会自动将前两个字段绑定到ChildDTO的前两个参数,后两个字段绑定到Parent的构造函数,再把生成的Parent实例作为第三个参数传给ChildDTO。
3. 方案二:显式使用row().convert()转换
如果你希望手动构造Parent的行记录并转换,可以用row(...).convert()方法:
var result = dslContext.select( CHILD.ID, CHILD.NAME, // 把Parent的字段包装成行,直接转换为Parent Record DSL.row(PARENT.ID, PARENT.NAME).convert(Parent::new) ) .from(CHILD) .join(PARENT).on(CHILD.PARENT_ID.eq(PARENT.ID)) // 直接用ChildDTO的构造函数接收三个参数 .fetch(Records.mapping(ChildDTO::new));
关键错误修正
你之前的代码用了PARENT.child(),这是从Parent关联所有Child的一对多方向,但你需要的是从Child关联单个Parent的多对一查询,所以必须从CHILD表出发,关联PARENT表,而不是反过来。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

