我正在为我的项目使用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中有效地获取这些值。
答案 0 :(得分:1)
使用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
用于连接的连接条件来自映射的连接列。这意味着JPQL用户通常不必知道每个关系的连接方式。在某些情况下,最好在连接条件中附加附加条件,通常在外连接的情况下。这可以通过ON子句来完成。
答案 1 :(得分:0)
也可以通过单一连接来完成:
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();