JPA 计算其子类的一对多关系

JPA counting its subclass for one to many relationship

我正在为我的项目使用 JPA,我想知道有什么方法可以计算它的子class 的一对多关系。例如,假设有一个包含多个项目的订单 class,我需要显示一个订单列表。

@Entity
@Table
public class Order {
    ...
    @Id
    private Long orderId;
    @OneToMany
    private List<OrderItem> orderItems;
}

对于列表,我需要显示订购了多少商品以及取消了多少商品。所以,我添加了这样的函数

    @OneToMany
    private List<OrderItem> orderItems;
    ...
    public Long countOrderedItems() {
        Long count = 0;
        orderItems.forEach(orderItem -> {
            if(orderItem.getStatus().equals(Status.ORDERED)){
                count++;
            }
        });
        return count;
    }
    public Long countCancelItems() {
        Long count = 0;
        orderItems.forEach(orderItem -> {
            if(orderItem.getStatus().equals(Status.CANCEL)){
                count++;
            }
        });
        return count;
    }

但是,这看起来效率低下,我想在从存储库获取数据时直接获取这两个值,例如:

@Query("SELECT o, (SELECT COUNT(oi) FROM OrderItem oi WHERE oi.Order.orderId = o.orderId AND oi.status = 'ORDERED') FROM Order o"); 

但是,我知道这不是正确的 JPQL,我想知道如何在 JPA 中有效地获取这些值。

使用 JPA 2.1 功能 JOIN ON

select o, count(io), count(io2) from Order o 
left join o.irderItem oi on oi.status = 'ORDERED'
left join o.irderItem ui on ui.status = 'CANCELED'
group by s

The join condition used for a join comes from the mapping's join columns. This means that the JPQL user is normally free from having to know how every relationship is joined. In some cases it is desirable to append additional conditions to the join condition, normally in the case of outer joins. This can be done through the ON clause.

也可以通过单连接完成:

HSQL:

select o, 
sum(case when oi.itemStatus = 'ORDERED' then 1 else 0 end), 
sum(case when oi.itemStatus = 'CANCELED' then 1 else 0 end) 
from OrderItem oi 
right outer join Order o on oi.orderId = o.id
group by o.id

JPA 存储库:

@Query("select new example.springboot.jpa.custom.OrderSummary(o, " +
        "sum(case when oi.itemStatus = 1 then 1 else 0 end) as orderedItems, " +
        "sum(case when oi.itemStatus = 1 then 1 else 0 end) as canceledItems)  " +
        "from OrderItem oi right join oi.customOrder o group by o")
List<OrderSummary> findAllOrdersSummary();

您可以在此处找到完整示例: https://github.com/abhilekhsingh041992/spring-boot-samples/blob/master/jpa/src/main/java/example/springboot/jpa/repository/OrderRepository.java