: 검색 조건이 고정되어 있고 단순하다면 특정 조건으로 조회하는 기능을 만들면 된다.
public interface OrderDataDao {
Optional<OrderData> findById(OrderNo id);
List<OrderData> finidByOrderer(String ordererId, Date fromDate, Date toDate);
...
}
Java
복사
: 그러나 목록 조회와 같은 기능은 다양한 검색 조건을 조합하여 진행할 때가 있다.
: 필요한 조합마다 find 메서드를 정의할 수 있으나 이는 좋은 방법이 아니다. 조합에 대한 요구사항이 증가할수록 정의해야할 find 메서드도 증가하기 때문이다.
: 이렇게 검색 조건을 다양하게 조합해야할 때 사용할 수 있는 것이 스펙이다. 스펙은 애그리거트가 특정 조건을 충족하는지를 검사할 때 사용하는 인터페이스다.
public interface Spefictation<T> {
public boolean isAtisfiedBy(T agg);
}
Java
복사
: isSatisfiedBy() 메서드의 agg 파라미터는 검사 대상이 되는 객체다. 스펙을 리포지터리에 사용하면 agg는 애그리거트 루트가 되고 스펙을 DAO에 사용하면 agg는 검색 결과로 리턴할 데이터 객체가 된다.
: isSatisfiedBy() 메서드는 검사 대상 객체가 조건을 충족하면 true를 리턴하고 그렇지 않으면 false를 리턴한다.
public class OrdererSpec implements Specification<Order> {
private String ordererId;
public OrdererSpec(String ordererId) {
this.ordererId = ordererId;
}
public boolean isSatisfiedBy(Order agg) {
return agg.getOrdererId().getMemberId().getId().equals(ordererId);
}
}
Java
복사
: 리포지터리나 DAO는 검색 대상을 걸러내는 용도로 스펙을 사용한다. 만약 리포지터리가 메모리에 모든 애그리거트를 적재하고 있다면 stream 형태로 api를 작성해도 괜찮다.
: 리포지터리가 스펙을 이용해서 검색 대상을 걸러주므로 특정 조건을 충족하는 애그리거트를 찾고 싶으면 원하는 스펙을 생성해서 리포지터리에 전달해주기만 하면 된다.