⇒ specification(스펙) 사용!
public interface Specifation<T>{
public boolean isSatisfiedBy(T agg);
}
→ agg(애그리거트 객체)가 조건을 충족하는지 boolean값을 리턴한다.
public class OrdereSpec implements Specification<Order> {
private String ordererId;
public OrdererSpec(String ordererId) {
this.ordererId = ordererId; //비교 대상
}
//Order 애그리거트 객체가 특정 고객의 주문인지 확인하는 스펙 구현
public boolean isSatisfiedBy(Order agg) {
return agg.getOrdererId().getMemberId().getId().equals(ordererId);
}
}
public class MemoryOrderRepository implements OrderRepository {
public List<Order> findAll(**Specification spec**) {
List<Order> allOrders = findAll();
return allOrders.stream().filter(order -> **spec.isSatisfiedBy(order)**).collect(toList());
}
}
Specification<Order> ordererSpec = new OrdererSpec("madvirus"); //특정 스펙 생성
List<Order> orders = orderRepository.findAll(ordererSpec); //리포지터리에 전달
public class AndSpec<T> implements Specification<T> {
private List<Specification<T>> specs;
public AndSpecification(Specification<T> ... specs) {
this.specs = Arrays.asList(specs);
}
public boolean isSatisfiedBy(T agg) {
for (Specification<T> spec : specs){
if (!spec.isSatisfiedBy(agg)) return false;
}
return true;
}
}
Specification<Order> ordererSpec = new OrdererSpec("madvirus");
Specification<Order> orderDateSpec = new OrderDataSpec(fromDate,toDate);
AndSpec<T> spec = new AndSpec(ordererSpec,orderDateSpec); //여러 스펙 전달
List<Order> orders = orderRepository.findAll(spec); //and스펙을 리포지토리에 전달
But, 앞선 리포지터리 코드는 모든 애그리거트 조회 후 스펙을 이용해서 걸러내는 방식이었다.
⇒ JPA를 위한 스펙 구현