我正在为我的项目使用JPA,我想知道有任何方法可以计算其一个与许多关系的子类。例如,假设有一个有多个项目的订单类,我需要显示订单列表。
@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功能在
上加入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
使用用于连接的联接条件来自映射的联接列。这意味着JPQL用户通常不必知道如何加入每个关系。在某些情况下,通常需要将其他条件添加到联接条件上,通常在外部联接情况下。这可以通过on子句完成。
也可以通过单个加入来完成:
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/src/main/java/java/java/springboot/springboot/jpa/jpa/repository/redorepository/orderrepository.java