当前位置: 首页 > 知识库问答 >
问题:

用jOOQ加载PostgreSQL树

堵才哲
2023-03-14

我在PostgreSQL中有以下结构:

TableA has many TableB has many TableC

这三个表(简化)如下:

create table TableA (
   idA int,
   nameA varchar(100));


create table TableB (
   idA int,
   idB int,
   nameB varchar(100));


create table TableC (
   idA int,
   idB int,
   idC int,
   nameC varchar(100));

我需要在PostgreSQL上运行jOOQ,选择TableA,但它也应该从TableBTableC加载任何相关的行。有没有办法运行单个jOOQ语句来加载这棵树?我知道我可以使用连接s来执行此操作,但我正在尝试避免Java中的任何循环

共有1个答案

尤飞尘
2023-03-14

从jOOQ 3.15开始,可以使用标准的SQL多集运算符嵌套集合,该运算符使用SQL/XML或SQL/JSON进行模拟

var result =
ctx.select(
      TABLE_A.ID_A, TABLE_A.NAME_A,
      multiset(
        select(
          TABLE_B.ID_B, TABLE_B.NAME_B,
          multiset(
            select(TABLE_C.ID_C, TABLE_C.NAME_C)
            .from(TABLE_C)
            .where(TABLE_C.ID_B.eq(TABLE_B.ID_B))
            .and(TABLE_C.ID_A.eq(TABLE_B.ID_A))
          ).as("c")
        )
        .from(TABLE_B)
        .where(TABLE_B.ID_A.eq(TABLE_A.ID_A))
      ).as("b")
    )
   .from(TABLE_A)
   .fetch();

结果的类型推断为:

Result<Record3<
  Integer,          // TABLE_A.ID_A
  String,           // TABLE_A.NAME_A
  Result<Record3< 
    Integer,        // TABLE_B.ID_B
    String,         // TABLE_B.NAME_B
    Result<Record2<
      Integer,      // TABLE_C.ID_C
      String        // TABLE_C.NAME_C
    >>
  >>
>> result = ...

如果您希望将其映射到一些自定义DTO数据结构中,例如。

record TableC(int idC, String nameC) {}
record TableB(int idB, String nameB, List<TableC> c) {}
record TableA(int idA, String nameA, List<TableB> b) {}

您可以使用jOOQ 3.15的新ad-hoc转换功能轻松做到这一点:

List<TableA> result =
ctx.select(
      TABLE_A.ID_A, TABLE_A.NAME_A,
      multiset(
        select(
          TABLE_B.ID_B, TABLE_B.NAME_B,
          multiset(
            select(TABLE_C.ID_C, TABLE_C.NAME_C)
            .from(TABLE_C)
            .where(TABLE_C.ID_B.eq(TABLE_B.ID_B))
            .and(TABLE_C.ID_A.eq(TABLE_B.ID_A))
          ).as("c").convertFrom(r -> r.map(Records.mapping(TableC::new)))
        )
        .from(TABLE_B)
        .where(TABLE_B.ID_A.eq(TABLE_A.ID_A))
      ).as("b").convertFrom(r -> r.map(Records.mapping(TableB::new)))
    )
   .from(TABLE_A)
   .fetch(Records.mapping(TableA::new));

所有映射都是类型安全、编译时检查和无反射的

您可以使用jOOQ 3.14的SQL/XML或SQL/JSON支持来实现这一点,请参阅此处的博客文章

如果类路径上有Gson或Jackson,它们可用于将XML或JSON结构映射回Java类层次结构。手册中关于ConverterProvider的页面给出了一个示例

本质上:

ctx.select(
     jsonObject(
       key("idA").value(TABLE_A.ID_A),
       key("nameA").value(TABLE_A.NAME_A),
       key("b").value(
         select(jsonArrayAgg(jsonObject(
           key("idB").value(TABLE_B.ID_B),
           key("nameB").value(TABLE_B.NAME_B),
           key("c").value(
             select(jsonArrayAgg(jsonObject(
               key("idC").value(TABLE_C.ID_C),
               key("nameC").value(TABLE_C.NAME_C)
             )))
             .from(TABLE_C)
             .where(TABLE_C.ID_B.eq(TABLE_B.ID_B))
           )
         )))
         .from(TABLE_B)
         .where(TABLE_B.ID_A.eq(TABLE_A.ID_A))
       )
     )
   )
   .from(TABLE_A)
   .fetch();

另请参阅此处的相关问题:

  • jOOQ-具有多对多关系的嵌套对象
  • 具有一对多关系的jooq单个查询
  • JOOQ pojos具有一对多和多对多的关系

请注意,JSON\u ARRAYAGG()将空集聚合为空集,而不是空集。如果这是一个问题,请使用COALESCE()

 类似资料:
  • 在我的Java项目中,我是usinq、JOOQ,我希望更新JSONB值。但我的建造失败了。 我写了一段代码: 我收到了下一条信息: 我犯错的地方?

  • 数据库是PostgreSQL 10,JOOQ版本是3.10.8。 是我在JOOQ上做错了什么,还是这是一个问题,可能已经在一些新版本中修复了?

  • 如果我用ctx.insertinto来做这个...很好用。我最初使用的是Jooq3.14.0,但升级到最新的3.14.4对此没有帮助。生成的Keys类一定有问题,因为在初始化Keys类之前一切都正常工作。是Postgresql表结构出了问题,还是代码生成出了问题? 完整回购如下:https://github.com/eriran/criminal-api/tree/security-tumpt

  • 我知道jOOQ将在不支持它的系统(如PostgreSQL)上模拟SQLMERGE。 我有一个带有串行(自动增量)id列和字符串uri列的表。我想在我的数据库中使用数字ID而不是URI,所以我必须确保在ID查找表中有一个URI。因此,按照jOOQ手册中的示例,我认为这将起作用: 这给了我一个这样的语句: 但是日志说jOOQ继续并尝试用绑定值执行查询。但是该表从未更新。所以我猜jOOQ没有在Postg

  • 问题内容: 我是PostgresSQL的新手,我正尝试加载以下格式的数据: 记录超过1万,某些列可能包含NULL数据。当我尝试这样做时: 我收到以下错误:ERROR:最后一个预期的列SQL状态之后的多余数据:22P04 我已经检查了列,它们还可以。这意味着不会遗漏任何列。 希望有人能帮忙。提前谢谢。 问题答案: 应该是 对我有用

  • 回到Jooq2.5,看起来可以通过FactoryOperations类设置PostgreSQL搜索路径,但Jooq3.5中没有该类。显然,FactoryOperations分为DSL和DSLContext,但我似乎找不到use(Schema)方法的结尾。如何在较新版本的jOOQ中设置PostgreSQL搜索路径?