JOOQ 使用另一个 POJO 获取 POJO 对象 - table 中的外键

JOOQ get POJO object with another POJO - foreign key in table

我是 JOOQ 的新手,遇到问题但找不到解决方案。我有一个包含 2 个表的简单数据库:SellersClients - sql 下面:

CREATE TABLE Sellers
(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL,
);


CREATE TABLE Clients
(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL,
seller_id int,
FOREIGN KEY (seller_id) REFERENCES Sellers(id)
);

Clientforeign key,它定义了哪个Seller分配给他。

我想使用 JOOQ 从数据库中获取客户端,但使用 join() 也会为每个客户端获取 Seller 对象。可能吗?如果是这样该怎么做?这是我的 POJO 对象:

public class Seller {
    private final SimpleIntegerProperty id = new SimpleIntegerProperty();
    private final SimpleStringProperty name = new SimpleStringProperty();

    ...
    //setters and getters here
    ...
}

public class Client {
    private final SimpleIntegerProperty id = new SimpleIntegerProperty();
    private final SimpleStringProperty name = new SimpleStringProperty();
    private final SimpleIntegerProperty sellerId = new SimpleIntegerProperty();
    //private Seller seller; //not working
    ...
    //setters and getters here
    ...
}

这是我获取客户的 JOOQ 代码:

context.select()
    .from(CLIENTS)
    .join(SELLERS)
    .on(CLIENTS.ID.eq(SELLERS.ID))
    .fetchInto(Client.class);

我应该改变什么才能得到我想要的?

查看 Lukas Eder(jOOQ 的作者)和其他一些 jOOQ 用户之间的对话 here。 Garrett Wilson 的用例看起来与您的非常相似(您有 Client:Seller,他有 Book:Author)。

说了很多,但从设计上看,jOOQ 似乎并不适合在您获取的 Client 记录中自动补充 Seller 实例。这是与 ORM 相关的经典 N+1 问题(即由客户查询触发的针对 table 卖家的多次查询)。

一个建议是将您的连接分解为离散的查询:

select * from Client where ...
select * from Seller where id in (select seller_id from Client where ...)

... 然后在应用程序的某处执行 client.setSeller() 类型逻辑。在这种情况下,您可以避免 N+1 问题,并且不需要依赖编写自定义任何 RecordMapper 类型。

我不是 jOOQ 专家,但我过去使用的方法是在一个查询中返回分层类型的列时对我来说效果很好:

  1. 定义自定义记录映射器以将您的 jOOQ Record 映射到您的域 type/POJO
  2. 定义一个自定义 RecordMapperProvider 并使用它来创建 DSLContext 单例,该单例将传递给您查询的任何组件(例如通过依赖注入)
  3. 使用前面提到的 DSLContext,编写您的查询并使用 fetchInto() 指定您的目标类型(应该在您的 RecordMapperProvider 中说明)

在前面提到的对话中,Lukas 在文档中添加了一个 link 关于使用自定义 RecordMapperProvider 实例,所以这很可能是惯用的。

希望对您有所帮助。