我正在尝试使用 jOOQ 从数据库中获取复杂的结构。我将尝试解释问题所在的示例。
所以,假设我们有类 Foo、Bar 和 Bazz:
public class Foo {
private String fooName;
private List<Bar> bars;
}
public class Bar {
private Bazz bazz;
}
public class Bazz {
private String name;
}
我想获取并填充 Foo -> List
我试过
MULTISET
并且它有效,但我想避免子查询。我想使用JOIN
获取和映射它。我想知道是否有可能使用反射来获取它,比如this.
这是
MULTISET
的例子:
public List<FooResponse> findByFooName(String fooName) {
return ctx().select(FOO.asterisk(),
multiset(select(BAR.asterisk(),
BAR.bazz().as("bazz"))
.from(BAR)
.where(BAR.FOO_ID.eq(FOO.ID))).as("bars"))
.from(FOO)
.where(FOO.FOO_NAME.eq(fooName))
.fetchInto(FooResponse.class);
}
在您的特定情况下,您可以使用
JOIN
和 GROUP BY
/ MULTISET_AGG
嵌套,而不是使用 MULTISET
值构造函数,因为您只嵌套了一层嵌套集合(第二层嵌套不是集合)。主要区别在于当您没有任何BAR
FOO
时会发生什么。通过聚合,这会产生一个 NULL
值,而不是一个空集合。
但是,API 中存在一些限制(例如 #15007、#13937),这使得使用
DefaultRecordMapper
(fetchInto(X.class)
调用)有点困难。这是使用 ad-hoc 转换 和类型安全的解决方案:
ctx().select(
FOO.FOO_NAME,
multisetAgg(
// Add more BAR columns here, if needed
row(
// Add more BAZZ columns here, if needed
BAR.bazz().NAME
).mapping(Bazz::new)
).convertFrom(r -> r.map(Records.mapping(Bar::new)))
)
.from(FOO)
.join(BAR).on(BAR.FOO_ID.eq(FOO.ID))
.groupBy(FOO.ID)
.where(FOO.FOO_NAME.eq(fooName))
.fetch(Records.mapping(Foo::new));
这是假设你有相关的构造函数。如果你不这样做,你可以随时恢复到每个级别的
into(X.class)
电话。
使用 jOOQ 的代码生成器 的一个好处是您拥有类型安全的嵌套集合映射,如上所示。