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

标签 java jooq

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

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

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

最佳答案

使用嵌套集合

对于较新版本的 jOOQ,您通常会使用一组 ORDBMS 功能,包括:

您将编写类似这样的内容来生成 jOOQ 类型:

Result<Record2<UserRecord, Result<Record1<RoleRecord>>>> result =
dsl.select(
        USER,
        multiset(
            selectFrom(USER_ROLE.role())
            .where(USER_ROLE.USER_ID.eq(USER.ID))
        ))
   .from(USER)
   .where(USER.U_EMAIL.equal(email))
   .fetch();

或者,通过使用所述 ad-hoc converters , 生成您自己的类型:

List<User> result =
dsl.select(
        USER.U_ID,
        USER.U_EMAIL, 
        ...
        multiset(
            selectFrom(USER_ROLE.role())
            .where(USER_ROLE.USER_ID.eq(USER.ID))
        ).convertFrom(r -> r.map(Records.mapping(Role::new))))
   .from(USER)
   .where(USER.U_EMAIL.equal(email))
   .fetch(Records.mapping(User::new));

历史答案/备选方案

为了完整起见,还有其他方法可以实现上述内容:

将 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()

关于java - jOOQ 我可以将两个表的连接提取到各自的 POJO 中吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38222957/

相关文章:

java - Unity AndroidJavaClass.CallStatic<Enum> on Android 插件。这可能吗?

java - 如何将代码转换为泛型方法 - Object.class

java - 没有函数的 DefaultTransactionProvider 的 JOOQ 交易

java - jooq - 从 POJO 插入时排除 id 字段

json - 使用 JOOQ 将数据插入 postgres 中的 JSON 列

java - ViewPager.setAdapter 需要 200 毫秒到 300 毫秒才能执行

java - 二进制文件IOException

java - cobertura-maven-plugin 2.6 托管在任何地方?

java - 在维护类型的同时使用条件过滤 JOOQ 生成的表

java - jOOQ 转换器和类型