【问题标题】:How to properly get results from JPA JOIN request?如何从 JPA JOIN 请求中正确获取结果?
【发布时间】:2020-01-29 00:33:03
【问题描述】:

我有两个 JPA 实体:

@Entity
public class ClientEntity {
   ...
   @OneToMany(fetch = LAZY)
   private List<OrderEntity> orders;
}

@Entity
public class OrderEntity {
   ...
   @ManyToOne
   private ClientEntity client;
}

我正在使用 JPA 规范 API 进行 LEFT OUTER JOIN:

public static Specification<ClientEntity> allClientsOrders() {
    return (root, query, cb) -> {
        Join<ClientEntity, TestOrderEntity> join = root.join("orders", JoinType.LEFT);
        return cb.and();
    };
}

现在我需要得到标准的 JOIN 结果:如果一个客户在 DB 中有 3 个订单,我希望他每次返回 3 次,并有另一个订单。但是,它向我返回了 3 次客户,但每次客户都有所有 3 个订单。

正如我在日志中看到的那样,Java 正确发送了第一个 SQL 查询,然后像往常一样发送其他查询以向客户端填充订单。

如何防止这种情况并以一个客户 - 一个订单对的形式获得结果?

【问题讨论】:

    标签: java database jpa spring-data-jpa left-join


    【解决方案1】:

    没有办法阻止客户端只加载关系的一部分。

    但是你描述的目的不需要加入操作。相反,搜索订单。您将获得 3 个订单。每个订单都与一个客户相关,因此您将获得所需的内容:3 个订单对象,每个对象都与一个客户组合。

    如果由于某种原因您希望查询返回这两种类型的组合,请考虑以下方法:定义一个新的 bean/DTO,它将表示您的 2 个对象的每个组合的字段的投影。然后像下面这样使用JPQL:

    select new mypackage.MyJoinDto (
        c.id,
        c.firstName,
        c.lastName,
        ...
        o.productName,
        o.orderDate,
        ...
    )
    from ClientEntity c left outer join TestOrderEntity o
        on o.clientId = c.id
    

    这个 MyJoinDto 不需要任何 JPA 注释。

    【讨论】:

    • 不幸的是,我需要 JOIN 行为,因为我还需要将没有任何订单的客户添加到列表中。根据您的回答,我唯一的选择似乎是不使用规范。
    • @OlegE:如果您觉得这个答案有帮助,您可以通过投票来表明这一点。
    猜你喜欢
    • 2018-12-15
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多