我正在使用JOOQ3.17.6和Kotlin,不知道如何检索和填充A-〉B-〉C关系。
给定一些类Foo-〉Bar-〉Baz
data class Foo(
val fooName: String,
val bar: Bar
)
data class Bar(
val barName: String,
val baz: Baz
)
data class Baz(
val bazName: String
)
如果我只想检索Bar
,这可以相当容易地完成
context.select(
BAR.barName,
BAR.baz().as("baz")
).from(BAR)
.where(BAR.barName.eq("first"))
fetchOneInto(Bar::class.java)
我的问题是当我想获取整个树Foo-〉Bar-〉Baz时也要这样做。下面的代码将失败,因为Bar
类的baz
没有填充,因为Jooq显然不知道从哪里获取它。
context.select(
Foo.fooName,
FOO.bar().as("bar")
).from(FOO)
.where(FOO.fooName.eq("first"))
.fetchOneInto(Foo::class.java)
我可以执行类似于此处所述的https://www.jooq.org/doc/3.17/manual/sql-building/table-expressions/tables-as-selectfield/操作,查询将如下所示
context.select(
FOO,
FOO.bar(),
FOO.bar().baz()
).where(FOO.fooName.eq("first"))
.fetch()
.map { /* do actual mapping here */ }
但是,如果实体更复杂,具有4-5-6个引用,每个引用具有10+个字段,则这种Map变得相当乏味。
另一种方法是在实体上保留id而不是域类型,即
data class Foo(
val name: String,
val barId: String
)
并且在我们实际需要引用实体时执行DB调用,但是由于我们正在从Hibernate迁移,这种更改需要做的工作比预期的要多。
1条答案
按热度按时间o7jaxewo1#
使用反射
您最初的尝试表明,使用基于反射的方法来Map数据很好,所以您可以继续这样做。这将是最简单的,但缺乏类型安全,存在出错的风险。
这是使用
Settings.namePathSeparator
标记(默认为"."
)计算DefaultRecordMapper
中嵌套对象的路径。如果
Field.getName()
是MY_field.MY_nested_field
(区分大小写!),则此字段的值将被视为嵌套值MY_nested_field
,该值是在嵌套POJO上设置的使用类型安全Map器
如果你想要类型安全,你必须在你的查询中模仿目标数据结构,例如。
当然,您也可以通过投影
FOO.bar()
和FOO.bar().baz()
来增加一级嵌套,以避免单独列出列,但前提是您的目标数据结构也以这种方式嵌套。这是一个很好的提醒,提醒您问问自己是否真的需要投影 * 所有 * 列,或者从性能的Angular 来看,显式列出列在这里可能不是更好的方法。