jOOQ 我可以将两个表的连接提取到各自的 POJO 中吗
jOOQ can I fetch a join of two tables into the respective POJOs
在 jOOQ 中,如果我想获取一行 table 到 jOOQ 自动生成的 POJO 中,例如:
dsl.selectFrom(USER)
.where(USER.U_EMAIL.equal(email))
.fetchOptionalInto(User.class);
现在,假设我想在两个 table 之间进行连接,例如USER
和 ROLE
,如何将结果提取到这两个 table 的 POJO 中?
正在将 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
,而不是空集 []
。
继续 Lukas Eder 的精彩回答:
如果您需要 return 中的列表结构,或者您无法在 POJO 中验证 equals 或 hashcode,您可以将其提取到 List
List<Pair<UserPojo, 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))
.fetch(record -> {
UserPojo userPojo = r.into(USER).into(UserPojo.class);
RolePojo rolePojo = r.into(ROLE).into(RolePojo.class);
return new ImmutablePair<>(zoneEntity, userEntity);
});
在 jOOQ 中,如果我想获取一行 table 到 jOOQ 自动生成的 POJO 中,例如:
dsl.selectFrom(USER)
.where(USER.U_EMAIL.equal(email))
.fetchOptionalInto(User.class);
现在,假设我想在两个 table 之间进行连接,例如USER
和 ROLE
,如何将结果提取到这两个 table 的 POJO 中?
正在将 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
,而不是空集 []
。
继续 Lukas Eder 的精彩回答:
如果您需要 return 中的列表结构,或者您无法在 POJO 中验证 equals 或 hashcode,您可以将其提取到 List
List<Pair<UserPojo, 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))
.fetch(record -> {
UserPojo userPojo = r.into(USER).into(UserPojo.class);
RolePojo rolePojo = r.into(ROLE).into(RolePojo.class);
return new ImmutablePair<>(zoneEntity, userEntity);
});