kotlin jooq中的多个嵌套到一个关系

lawou6xi  于 2023-03-19  发布在  Kotlin
关注(0)|答案(1)|浏览(152)

我正在使用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迁移,这种更改需要做的工作比预期的要多。

o7jaxewo

o7jaxewo1#

使用反射

您最初的尝试表明,使用基于反射的方法来Map数据很好,所以您可以继续这样做。这将是最简单的,但缺乏类型安全,存在出错的风险。

context.select(
  Foo.fooName,
  FOO.bar().as("bar"),
  FOO.bar().baz().as("bar.baz") // This is the magic
).from(FOO)
  .where(FOO.fooName.eq("first"))
  .fetchOneInto(Foo::class.java)

这是使用Settings.namePathSeparator标记(默认为".")计算DefaultRecordMapper中嵌套对象的路径。
如果Field.getName()MY_field.MY_nested_field(区分大小写!),则此字段的值将被视为嵌套值MY_nested_field,该值是在嵌套POJO上设置的

使用类型安全Map器

如果你想要类型安全,你必须在你的查询中模仿目标数据结构,例如。

context.select(
  FOO.NAME,
  // List all of Foo's columns here
  row(
    FOO.bar().NAME,
    // List all of Bar's columns here
    row(
      FOO.bar().baz().NAME
      // List all of Baz's columns here
    ).mapping(::Baz)
  ).mapping(::Bar)
).from(FOO)
  .where(FOO.fooName.eq("first"))
  .fetchOne(Records.mapping(::Foo))

当然,您也可以通过投影FOO.bar()FOO.bar().baz()来增加一级嵌套,以避免单独列出列,但前提是您的目标数据结构也以这种方式嵌套。
这是一个很好的提醒,提醒您问问自己是否真的需要投影 * 所有 * 列,或者从性能的Angular 来看,显式列出列在这里可能不是更好的方法。

相关问题