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

JOOQ获取外键表

桓高澹
2023-03-14

我有三张桌子:

Users
Keys
UserKeys

用户键表具有来自用户和键表的主键,以建立用户和键之间的关系。

如何使用所有相关键获取用户?

如果存在其他表(例如,UserRoles)等,该怎么办?通常,如何获取用户和所有通过外键表相关的相关行?

共有1个答案

西门品
2023-03-14

我假设您正在使用jOOQ的代码生成器。编写连接就像在SQL中编写连接一样:

ctx.select() // Optionally, list columns here, explicitly
   .from(USERS)
   .join(USER_KEYS).on(USERS.ID.eq(USER_KEYS.USER_ID))
   .join(KEYS).on(USER_KEYS.KEY_ID.eq(KEYS.ID))
   .where(USERS.NAME.eq("something"))
   .fetch();

如果存在其他表(例如UserRoles)等怎么办?通常,如何获取用户和所有关联的行,通过外键表关联?

我不确定这是否还是同一个问题。上述内容可能是关于如何进行连接的,这一部分似乎更具体地介绍了如何获取嵌套集合?

因为一旦连接多条路径,连接总是会产生笛卡尔积,这是不可取的。从jOOQ 3.14开始,如果您的数据库支持,您可以使用SQL/XML或SQL/JSON作为解决方法。从jOOQ 3.15开始,可以使用MULTISET。例如,JSON解决方案可能如下所示:

List<User> users =
ctx.select(jsonObject(
     jsonEntry("id", USERS.ID),
     jsonEntry("name", USERS.NAME),
     jsonEntry("keys", field(
       select(jsonArrayAgg(jsonObject(KEYS.NAME, KEYS.ID)))
       .from(KEYS)
       .join(USER_KEYS).on(KEYS.ID.eq(USER_KEYS.KEY_ID))
       .where(USER_KEYS.USER_ID.eq(USER.ID))
     )),
     jsonEntry("roles", field(
       select(jsonArrayAgg(jsonObject(ROLES.NAME, ROLES.ID)))
       .from(ROLES)
       .join(USER_ROLES).on(ROLES.ID.eq(USER_ROLES.ROLE_ID))
       .where(USER_ROLES.USER_ID.eq(USER.ID))
     ))
   ))
   .from(USERS)
   .where(USERS.NAME.eq("something"))
   .fetchInto(User.class);

假设用户类看起来像这样,并且类路径上有Gson或Jackson,可以从JSON映射到Java数据结构:

class Key {
  long id;
  String name;
}

class Role {
  long id;
  String name;
}

class User {
  long id;
  String name;

  List<Key> keys;
  List<Role> roles;
}

当然,您不必映射到Java数据结构并直接生成JSON结果,而无需进一步映射。有关更多详细信息,请参阅这篇博客文章,或者这篇文章解释了如何使用MULTISET。

请注意,JSON_ARRAYAGG()将空集聚合到NULL中,而不是空[]中。如果有问题,请使用COALESCE()

MULTISET解决方案如下所示:

List<User> users =
ctx.select(
     USERS.ID,
     USERS.NAME,
     multiset(
       select(KEYS.NAME, KEYS.ID)
       .from(KEYS)
       .join(USER_KEYS).on(KEYS.ID.eq(USER_KEYS.KEY_ID))
       .where(USER_KEYS.USER_ID.eq(USER.ID))
     ).as("keys").convertFrom(r -> r.map(Records.mapping(Key::new))),
     multiset(
       select(ROLES.NAME, ROLES.ID)
       .from(ROLES)
       .join(USER_ROLES).on(ROLES.ID.eq(USER_ROLES.ROLE_ID))
       .where(USER_ROLES.USER_ID.eq(USER.ID))
     ).as("roles").convertFrom(r -> r.map(Records.mapping(Role::new)))
   )
   .from(USERS)
   .where(USERS.NAME.eq("something"))
   .fetch(Records.mapping(User::new));

使用各种Records.mapping()重载以及ad-hoc数据类型转换的上述方法假定存在不可变构造函数,例如如果您的类Java16条记录,您会得到:

record Key (int id, String name) {}
record Role (int id, String name) {}
record User (int id, String name, List<Key> keys, List<Role> roles) {}
 类似资料:
  • 是否有一种方法可以编程地列出所有在Jooq中作为外键的字段?它为外键生成了很多静态常量,但没有很好的方法以编程方式访问这些常量。 例如,我有一个表,其中有一个外键字段。在jOOQ中,假设我对的表对象有一个引用,那么似乎没有方法以编程方式获取对jOOQ字段对象的引用。因此,我现在唯一的解决方案是使用文字地图DataStructure在某个地方手动生成这些映射。似乎jooq可以为我做到这一点,我是不是

  • 我有一个主键值,我想获取一个记录以进行更新,所以现在我写: JOOQ知道我的表的主键(例如,它会生成onKey()方法等)-因此我希望得到如下结果: 但这似乎不是一件事。有没有更简洁的方法使用JOOQ API来做我想要的事情?

  • 我的数据库中有两个表: 如你所见,作者和书之间有一种关系:作者可以有很多书。在我的申请中,我想获取所有的作者,每个人都有他们的书籍收藏。现在我用代码实现了这个: 不幸的是,它需要对数据库进行许多查询。一个select用于获取作者,另外一个query用于为每个作者获取书籍。我试图连接表,但我不知道如何使用jooq正确解析结果。有什么想法吗?

  • 我搞错了吗?或者JOOQ真的不能正确地处理特定表使用次数超过一次的查询吗??如果是,为什么这个不修好?? 最好的问候,期待您的意见。

  • 我有一个问题..为什么要重复我在fetch方法中选择的内容。 所以我提供了CON\u CAL\u INSTANCE.DATE。min()在我的select子句中,为什么我必须在fetchOne(CON\u CAL\u INSTANCE.DATE.min())中重复它? 还是我做得不对?

  • 我一直在使用模式。方法来获取模式中的表列表,但今天我发现该方法返回的是执行jOOQ代码生成时存在的表列表,而不是此时存在的表。 我的具体用例是随着时间的推移创建表(自动分区),我们的Java服务对它们执行一些操作。 在jOOQ中有没有办法从DB中获取当前的表列表? 我可以求助于查询信息模式。直接使用表,但我更愿意重用来自jOOQ的方法(如果可用的话)。