public interface Specification<T> {
public boolean isSatisfiedby(T agg);
}
################################################################################################
public class OrdererSpec implements Specification<Order> {
private String ordererId;
public boolean isSatisfiedBy(Order agg) {
return agg.getOrdererId().getMemberId().getId().equals(ordererId);
}
}
################################################################################################
Specification<Order> ordererSpec = new OrdererSpec("madvirus");
List<Order> orders = orderRepository.findAll(ordererSpec);
Specification<Order> ordererSpec = new OrdererSpec("madvirus");
Specification<Order> ordererDateSpec = new OrdererDateSpec(fromDate, toDate);
AndSpec<T> spec = new AndSpec(ordererSpec, orderDateSpec);
################################################################################################
List<Order> orders = orderRepository.findAll(spec);
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaBuilder db);
}
################################################################################################
public class OrdererSpec implements Specification<Order> {
private String ordererId;
public Predicate toPredicate(Root<Order> root, CriteriaBuilder cb) {
return cb.equal(root.get(Order_.orderer)
.get(Orderer_.memberId).get(MemberId_.id),
ordererId);
}
}
################################################################################################
Specification<Order> ordererSpec = new OrdererSpec("madvirus");
List<Order> orders = orderRepository.findAll(ordererSpec);
public class OrderSpecs {
public static Specification<Order> orderer(String ordererId) {
return (root, cb) -> cb.equal(
root.get(Order_.orderer).get(Orderer_.memberId).get(MemberId_.id),
ordererId);
}
public static Specification<Order> between(Date from, Date to) {
return (root, cb) -> cb.between(root.get(Order_.orderDate), from, to);
}
}
public class AndSpecification<T> implements Specification<T> {
private List<Specification<T>> specs;
public AndSpecification(Specification<T> ... specs) {
this.specs = Arrays.asList(specs);
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaBuilder cb) {
Predicate[] predicates = specs.stream()
.map(spec -> spec.toPredicate(root, cb))
.toArray(size -> new Predicate[size]);
return cb.and(predicates);
}
}
public class OrSpecification<T> implements Specification<T> {
private List<Specification<T>> specs;
public OrSpecification(Specification<T>... specs) {
this.specs = Arrays.asList(specs);
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaBuilder cb) {
Predicate[] predicates = specs.stream()
.map(spec -> spec.toPredicate(root, cb))
.toArray(Predicate[]::new);
return cb.or(predicates);
}
}
public class Specs {
public static <T> Specification<T> and(Specification<T> ... specs) {
return new AndSpecification<>(specs);
}
public static <T> Specification<T> or(Specification<T> ... specs) {
return new OrSpecification<>(specs);
}
}
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaBuilder cb);
}
public interface OrderRepository {
List<Order> findAll(Specification<Order> spec, String ... orders);
}
@Override
public List<Order> findAll(Specification<Order> spec, String ... orders) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> criteriaQuery = cb.createQuery(Order.class);
Root<Order> root = criteriaQuery.from(Order.class);
Predicate predicate = spec.toPredicate(root, cb);
criteriaQuery.where(predicate);
if (orders.length > 0) {
criteriaQuery.orderBy(JpaQueryUtils.toJpaOrders(root, cb, orders));
}
TypedQuery<Order> query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
검색 조건이 되는 루트 생성 ( Order.class ) 루트 생성후 toPredicate로 Predicate 생성
생성한 Predicate를 전달하기만 하면 된다.
리포지토리 구현 기술 의존