JOOQ 中有没有办法在没有多个数据库调用的情况下提取大量记录?

Is there a way in JOOQ to pull a number of records without multiple DB calls?

在我们的网络应用程序中,我们有许多地方可以让您在一个复杂的 form/view 中更新多个 table。在原始 SQL 中,我可能会 select 来自一堆 table 的一堆列,并在主要 table 以及相关的 parent/child 上编辑该记录] tables.

在休眠中,我可能只是为主要 table 提取一个 JPA 实体,并让休眠在我填充视图时获取 parent/child 关系。然后从我的视图中拉回实体并调用 entitymanger .perist/merge.

在 JOOQ 中,我有很多选项,但您似乎可以通过 selectFrom/fetch 提取主记录,然后使用 fetchChild fetchParent 提取类型化的相关记录,如下所示...

    LoadsRecord load = dslContext.selectFrom(LOADS)
            .where(LOADS.ID.eq(id))
            .fetchOne();
    SafetyInspectionsRecord safetyInspection = load.fetchParent(Keys.LOADS__FK_SAFETY_INSPECTION);

所以这样我就能够以类型安全的方式提取相关记录。唯一烦人的是我每次调用 fetchParent 或 fetchDhild 时都必须 运行 另一个完整查询。有没有办法一次急切地获取所有这些以避免多次往返数据库?

拥有这些 类 用于 CRUD 屏幕的 LoadsRecord 真的很棒,它使更新数据库变得容易。

使用连接的经典方法

您可以通过多种方式实现 to-one 关系。最简单的是简单的 JOINLEFT JOIN 如果关系是可选的。

例如:

Result<?> result =
ctx.select()
   .from(LOADS)
   .join(SAFETY_INSPECTIONS)
   .on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
   .fetch();

之后您可能想使用生成的记录,因此您可以使用各种映射工具将通用 Record 类型映射到两个 UpdatableRecord 类型以进行进一步的 CRUD:

for (Record r : result) {
    LoadsRecord loads = r.into(LOADS);
    SafetyInspectionsRecord si = r.into(SAFETY_INSPECTIONS);
}

使用嵌套记录

从 jOOQ 3.15 开始,#11812, MULTISET and ROW 运算符可用于创建嵌套的集合和记录。因此,在您的查询中,您可以这样写:

Result<?> result =
ctx.select(
      row(LOADS.ID, ...), 
      row(SAFETY_INSPECTIONS.ID, ...))
   .from(LOADS)
   .join(SAFETY_INSPECTIONS)
   .on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
   .fetch();

这已经有助于将嵌套数据结构映射到所需的格式。从jOOQ 3.17和#4727开始,你甚至可以直接使用table表达式来生成嵌套记录:

Result<Record2<LoadsRecord, SafetyInspectionsRecord>> result =
ctx.select(LOADS, SAFETY_INSPECTIONS)
   .from(LOADS)
   .join(SAFETY_INSPECTIONS)
   .on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
   .fetch();

这项新功能肯定会弥补 jOOQ 的最大差距之一。您甚至可以使用 implicit joins 将上述内容简化为:

Result<Record2<LoadsRecord, SafetyInspectionsRecord>> result =
ctx.select(LOADS, LOADS.safetyInspections())
   .from(LOADS)
   .fetch();