【问题标题】:jOOQ query with nested list带有嵌套列表的 jOOQ 查询
【发布时间】:2015-11-26 18:08:46
【问题描述】:

jOOQ 能否将查询结果映射到 POJO 中的多个嵌套列表?例如,我有一个 POJO VM,它代表一个虚拟机。它有一个“networks”属性,它是一个 Network 类型的列表。它还具有“hdds”属性,它是“HDD”类型的列表。该查询连接 VM、HDD 和网络表。我可以“获取”到 VM.class 并期望 jOOQ“做正确的事”吗?

【问题讨论】:

    标签: java sql orm jooq


    【解决方案1】:

    在 jOOQ 3.15 中使用 MULTISET

    从 jOOQ 3.15 开始,这里的首选方法是使用 MULTISET。假设您有:

    record Vm(String name, List<Network> networks, List<Hdd> hdds) {}
    

    你可以写

    List<Vm> result =
    ctx.select(
          VM.NAME,
          multiset(
            select(
              // Using implicit joins can help here, though entirely optional
              NETWORK_TO_VM.network().ID, 
              NETWORK_TO_VM.network().NAME)
            .from(NETWORK_TO_VM)
            .where(NETWORK_TO_VM.VM_ID.eq(VM.VM_ID))
          ).convertFrom(r -> r.map(Records.mapping(Network::new))),
          multiset(
            select(
              HDD_TO_VM.hdd().ID,
              HDD_TO_VM.hdd().NAME)
            .from(HDD_TO_VM)
            .where(HDD_TO_VM.VM_ID.eq(VM.VM_ID))
          ).convertFrom(r -> r.map(Records.mapping(Hdd::new)))
       )
       .from(VM)
       .fetch(Records.mapping(Vm::new));
    

    注意上面的方法是结合的:

    所有这些都是为了确保您可以直接从您的 SQL 查询中键入检查对象层次结构,该查询只需一次即可获取所有数据。

    在 jOOQ 3.14 中使用 SQL/XML 或 SQL/JSON 嵌套集合

    从 jOOQ 3.14 开始,这里的一个选项是 use SQL/XML or SQL/JSON to nest collections directly in SQL。例如:

    class Vm {
      String name;
      List<Network> networks;
      List<Hdd> hdds;
    }
    

    现在,你可以写:

    List<Vm> result =
    ctx.select(
          VM.NAME,
          field(
            select(jsonArrayAgg(jsonObject(
              key("id").value(NETWORK.ID),
              key("name").value(NETWORK.NAME),
              // ...
            )))
            .from(NETWORK)
            .join(NETWORK_TO_VM).on(NETWORK.NETWORK_ID.eq(NETWORK_TO_VM.NETWORK_ID))
            .where(NETWORK_TO_VM.VM_ID.eq(VM.VM_ID))
          ).as("networks"),
          field(
            select(jsonArrayAgg(jsonObject(
              key("id").value(HDD.ID),
              key("name").value(HDD.NAME),
              // ...
            )))
            .from(HDD)
            .join(HDD_TO_VM).on(HDD.HDD_ID.eq(HDD_TO_VM.HDD_ID))
            .where(HDD_TO_VM.VM_ID.eq(VM.VM_ID))
          ).as("hdds")
       )
       .from(VM)
       .fetchInto(Vm.class);
    

    请注意,JSON_ARRAYAGG() 将空集聚合到 NULL,而不是空集 []If that's a problem, use COALESCE()

    历史答案(jOOQ 3.14 之前)

    此类映射功能在 jOOQ 之类的库中只能在有限范围内实现的主要原因是,通过连接表和非规范化结果,jOOQ 不再具有正确删除顶级元组重复数据所需的信息(@ 987654341@ 在您的情况下)。实现 JPA 的流行 ORM 不受此限制,因为它们不允许您表达任意联接。

    但是您有一定的可能性将非规范化的结果集映射到嵌套集合中:

    【讨论】:

      猜你喜欢
      • 2014-07-19
      • 2019-08-09
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 1970-01-01
      • 2017-02-12
      相关资源
      最近更新 更多