jOOQ 我可以将两个表的连接提取到各自的 POJO 中吗

Posted

技术标签:

【中文标题】jOOQ 我可以将两个表的连接提取到各自的 POJO 中吗【英文标题】:jOOQ can I fetch a join of two tables into the respective POJOs 【发布时间】:2016-11-08 10:38:09 【问题描述】:

在 jOOQ 中,如果我想将表的一行提取到 jOOQ 自动生成的 POJO 中,例如:

dsl.selectFrom(USER)
                .where(USER.U_EMAIL.equal(email))
                .fetchOptionalInto(User.class);

现在,假设我想在两个表之间进行连接,例如USERROLE,如何将结果提取到这两个表的 POJO 中?

【问题讨论】:

用户和角色是如何关联的?一对多?多对一?多对多? 多对多,所以是的,还有一个表 UserToRole 也 【参考方案1】:

将 POJO 提取到 Map

这是使用ResultQuery.fetchGroups(RecordMapper, RecordMapper)的一种解决方案

Map<UserPojo, List<RolePojo>> result =
dsl.select(USER.fields())
   .select(ROLE.fields())
   .from(USER)
   .join(USER_TO_ROLE).on(USER.USER_ID.eq(USER_TO_ROLE.USER_ID))
   .join(ROLE).on(ROLE.ROLE_ID.eq(USER_TO_ROLE.ROLE_ID))
   .where(USER.U_EMAIL.equal(email))
   .fetchGroups(

       // Map records first into the USER table and then into the key POJO type
       r -> r.into(USER).into(UserPojo.class),

       // Map records first into the ROLE table and then into the value POJO type
       r -> r.into(ROLE).into(RolePojo.class)
   );

注意,如果您想改用 LEFT JOIN(如果用户不一定有任何角色,并且您想为每个用户获取一个空列表),则必须将 NULL 角色转换为空列出你自己。

确保您已激活在 POJO 上生成 equals()hashCode(),以便能够将它们作为键放入 HashMap

<pojosEqualsAndHashCode>true</pojosEqualsAndHashCode>

使用自定义的分层 POJO 并将它们提取到嵌套集合中

一个经常重复出现的问题是如何在 jOOQ 中获取嵌套集合,即如果您的结果数据结构如下所示:

class User 
  long id;
  String email;
  List<Role> roles;


class Role 
  long id;
  String name;

从 jOOQ 3.14 开始,如果您的 RDBMS 支持,您现在可以使用 SQL/XML 或 SQL/JSON 作为中间格式来嵌套集合,然后使用 Jackson、Gson 或 JAXB 将文档映射回您的Java 类(或者保留 XML 或 JSON,如果这是您首先需要的)。例如:

List<User> users =
ctx.select(
      USER.ID,
      USER.EMAIL,
      field(
        select(jsonArrayAgg(jsonObject(ROLE.ID, ROLE.NAME)))
        .from(ROLES)
        .join(USER_TO_ROLE).on(ROLE.ROLE_ID.eq(USER_TO_ROLE.ROLE_ID))
        .where(USER_TO_ROLE.USER.ID.eq(USER.ID))
      ).as("roles")
    )
    .from(USER)
    .where(USER.EMAIL.eq(email))
    .fetchInto(User.class);

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

【讨论】:

感谢您的回答。但只是想知道如何将其与fetchLazy 结合使用? @Kango_V:好点。这两个功能目前无法组合。我为此创建了一个功能请求:github.com/jOOQ/jOOQ/issues/6046。当然,您可以将 Cursor(来自 fetchLazy())转换为 Java 8 Stream,然后使用 collect() 对结果进行分组... 这对一对多关系有何作用?我们有一个特征表和一个层表,1 层可以有多个特征。所以想查询并得到输出,因为 Map> 字节对应于 tierID 和特征名称列表。 @user160108 使用fetchGroups(TIER_ID, FEATURE_NAME) @LukasEder 有效,有另一个查询是否也可以映射到像 Map> 这样的 pojo 用于一对多关系?

以上是关于jOOQ 我可以将两个表的连接提取到各自的 POJO 中吗的主要内容,如果未能解决你的问题,请参考以下文章

如何将2条记录(多对一)的Result对象映射到jOOQ中各自的记录对象?

使用来自两个不同数据库的两个表使用 JOOQ 构建左连接查询

JOOQ 连接两个具有相同列名的表

连接两个表的工作查询是完美的,除了我无法摆脱重复项

jOOQ & PostgreSQL:将从复杂 jsonb 中提取的嵌套 json 对象映射到自定义类型

带有嵌套列表的 jOOQ 查询