Я пытаюсь отфильтровать список объектов JPA, которые содержат несколько уровней вложенных списков. Мне нужно отфильтровать список верхнего уровня по критерию в списке, который на 2 уровня ниже.
Моему приложению предоставляется список заказов, который содержит список строк заказов, который содержит список OrderLineDetails. Я пытаюсь отфильтровать список orderLineDetail, который содержится в списке заказов, по самым последним статусам statusT для каждой строки заказа в списке. Конечным результатом должен быть список заказов, который содержит самый последний OrderLineDetail для каждой линии заказов. Я сталкиваюсь с проблемами, потому что список orderLineDetail является дочерним объектом на 2 уровня ниже объекта Order. Может кто-нибудь привести пример того, как это можно сделать? Спасибо за вашу помощь.
public class Order
private Long orderId;
@OneToMany(
mappedBy = "order",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER)
private List<OrderLine> orderLines = new ArrayList<>();
...
public class OrderLine
private Long orderLineId;
private Timestamp lastUpdate;
@OneToMany(mappedBy = "orderLine", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<OrderLineDetail> orderLineDetails;
@ManyToOne
@JoinColumn(name = "orderId")
private Order order;
...
public class OrderLineDetail
private Long orderLineDetailId;
private Integer status;
private Instant statusTs = Instant.now();
@ManyToOne
@JoinColumn(name = "orderLineId")
private OrderLine orderLine;
...
Не уверен, что есть лучший способ. Но это похоже на работу.
public List<Order> filterOrdersByMostRecentTs(List<Order> orderList) {
orderList.forEach(order -> {
order.getOrderLine().forEach(line -> {
List<OrderLineDetail> orderLineDetailList = line.getOrderLineDetail();
Map<Object, Object> o =
orderLineDetailList.stream().collect(
Collectors.groupingBy(OrderLineDetail -> OrderLineDetail.getOrderLine().getOrderLineId(),
Collectors.collectingAndThen(
Collectors.reducing((OrderLineDetail d1, OrderLineDetail d2) -> d1.getStatusTs().getEpochSecond() > d2.getStatusTs().getEpochSecond()? d1 : d2),
Optional::get)));
orderLineDetailList.clear();
o.forEach((k, v) -> orderLineDetailList.add((OrderLineDetail) v));
});
});
return orderList;
}