I want to get a list of object based on some parameters. Does the object belong to a particular category, does it have property x y z etc. I have created a fairly simple reposit
The below strategy is based on that the project uses domain objects as persistent objects also.
If the query is just for user searching(for example, an order searching ui), I'd like to invoke the repository directly in the interfaces component.
@Controller
public class OrderAdminController {
@RequestMapping(........)
public String search(@ModelAttribute OrderCriteria criteria) {
PagedList<Order> orders = orderRepository.findBy(criteria);
//criteria contains dateWhenPlaced, customerNameLike, orderStatus matching and so on.
.......
}
}
If the query contains domain concepts, I'd like to use a Specification. In this case, SQL filterting is finally used at infrastructure(for performance, we can't load all aggregates in memory and do filter by java ) but the domain logic does not leak(to application layer and infrastructure)
public class CancelOverdueOrdersBatch {
public void run() {
List<Order> overdues = orderRepository.
findSatisfying(new OverdueOrderSpecification(clock));
for (Order order: overdues) {
//.....cancel
}
}
}
public class OverdueOrderSpecification {
private Clock clock;
private int overdueMinutes = 30;
public OrderCriteria asCriteria() { //invoked by repository implementation
return new OrderCriteria.Builder().orderStatusEq(UNPAID).
placedBefore(overdueMinutesAgo()).build();
}
private Date overdueMinutesAgo() {
return ....//placedDate calculation based on clock.now() and overdueMinutes
}
}