CQRS
명령 모델
조회 모델
도메인 모델 -> 명령 모델
정렬, 페이징, 검색 조건 지정 등 -> 조회 모델
public interface Specification<T> {
public boolean isSatisfiedBy(T agg);
}
isSatisfiedBy
메서드agg
파라미터는 검사 대상이 되는 객체package org.springframework.data.jpa.domain;
public interface Specification<T> extends Serializable { // T -> JPA 엔티티 타입
//not, where, and, or 메서드 생략
@Nullable
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
public class OrderIdSpec implements Specification<OrderSummary> {
private String orderId;
public OrdererIdSpec(String orderId) {
this.ordererId = ordererId;
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.equal(root.get(OrderSummary_.ordererId), ordererId);
}
}
findAll()
메서드 사용public interface OrderSummaryDao extends Repository<OrderSummary, String> {
List<ORderSummary> findAll(Specification<OrderSummary> spec); //스펙 인터페이스를 파라미터로 가짐
}
//스펙 객체 생성
Specification<orderSummary> spec = new OrdererIdSpec("user1");
//findAll() 메서드 이용해서 검색
List<OrderSummary> results = orderSummaryDao.findAll(spec);
and
와 or
메서드and
메서드 : 두 스펙을 모두 충족하는 조건을 표현하는 스펙 생성or
메서드 : 두 스펙 중 하나 이상 충족하는 조건을 표현하는 스펙 생성Specification<OrderSummary> spec = OrderSummarySpecs.ordererId("user1")
.and(ORderSummarySpecs.orderDateBetween(from, to));
not
메서드Specification<OrderSummary> spec =
Specification.not(OrderSummarySpecs.ordererId("user1"));
where
메서드Specification<OrderSummary> spec =
Specification.where(createNullableSpec()).and(createOtherSpec());
OrderBy
사용해서 정렬 기준 지정findByOrdererIdOrderByNumberDesc()
,findByOrdererIdOrderByOrderDateDescNumberAsc()
->두 개 이상의 프로퍼티에 대한 정렬
Sort
를 인자로 전달find
메서드에 마지막 파라미터로 Sort
추가and
이용해서 두 Sort 객체 연결Sort sort = Sort.by("number").ascending();
List<OrderSummary> results = orderSummaryDao.findByOrdererId("user1", sort);
Pageable
타입 find
메서드에 파라미터로 전달하면 페이징 자동으로 처리Sort sort = Sort.by("name").descending(); //정렬 순서 지정
PageRequest pageReq = PageRequest.of(1, 2, sort);
List<MemberData> user = memberDataDao.findByNameLike("사용자%", pageReq);
findFirst3ByNameLikeOrderByName()
Specification<MemberData> spec = SpecBuilder.builder(MemberData.class)
.ifTrue(searchRequest.isOnlyNotBlocked(),
() -> MemberDataSpecs.nonBlocked())
.ifHasText(searchRequest.getName(),
name -> MemberDataSpecs.nameLike(searchRequest.getName())
.toSpec();
List<MemberData> result = memberDataDao.findAll(spec, Pagerequest.of(0,5));
public interface OrderSummaryDao
extends Repository<OrderSummary, String> {
@Query(""
select new com.myshop.order.query.dto.OrderView(
o.number, o.state, m.name, m.id, p.name
)
from Order o join o.orderLines ol. Member m, Product p
where o.orderer.memberId = :ordererId
and o.orderer.memberId.id = m.id
and index(ol) = 0
and ol.productId.id = p.id
order by o.number.number desc
"")
List<OrderView> findOrderView(String ordererId);
}
@Subselect
@Entity
로 매칭할 수 있는 유용한 기능@Subselect
로 조회한 @Entity
수정 불가@Subselect
의 값으로 지정한 쿼리를 from 절의 서브 쿼리로 사용@Immutable
@Synchronize