스프링 데이터 JPA는 2가지 방법으로 QueryDSL을 지원한다. - org.springframework.data.querydsl.QueryDslPredicateExecutor - org.springframework.data.querydsl.QueryDslRepositorySupport
첫 번째 방법은 리포지토리에서 QueryDslPredicateExecutor를 상속받으면 된다.
public interface ItemRepository extends JpaRepository<Item, Long>, QueryDslPredicateExecutor<Item>{}
이제 상품 리포지토리에서 QueryDSL을 사용할 수 있다.
//QueryDSL 사용 예제/*QueryDSL이 생성한 쿼리 타입으로 장난감이라는 이름을 포함하고 있으면서 10000~20000원인 상품을 검색*/QItem item = QItem.item;Iterable<Item> result = itemRepository.findAll( item.name.contains("장난감").and(item.price.between(10000,20000)) )
QueryDSL을 검색조건으로 사용하면서 스프링 데이터 JPA가 제공하는 페이징과 정렬 기능도 함께 사용할 수 있다.
public interface QueryDslPredicateExecutor<T>{ T findOne(Predicate predicate); Iterable<T> findAll(Predicate predicate); Iterable<T> findAll(Predicate predicate, OrderSpecifier<?>... orders); Page<T> findAll(Predicate predicate, Pageable pageable); long count(Predicate predicate);}
QueryDslPredicateExecutor는 편리하게 QueryDSL을 사용할 수 있지만 기능에 한계가 있다.
예를 들어 join, fetch를 사용할 수 없다.(JPQL의 묵시적 조인은 가능) 따라서 QueryDSL이 제공하는 다양한 기능을 사용하려면 JPAQuery를 직접 사용하거나 스프링 데이터 JPA가 제공하는 QueryDslRepositorySupport를 사용해야 한다.
스프링 데이터 JPA가 제공하는 QueryDslRepositorySupport를 상속받아 사용하면 조금 더 편리하게 QueryDSL을 사용할 수 있다.
public interface CustomOrderRepository{ public List<Order> search(OrderSearch orderSearch);}
스프링 데이터 JPA가 제공하는 공통 인터페이스는 직접 구현할 수 없기 때문에 CustomOrderRepository라는 사용자 정의 리포지토리를 만들었다.
//QuerydslRepositorySupport를 사용하는 코드public class OrderRepositoryImpl extends QuerydslRepositorySupport implements CustomOrderRepository{ public OrderRepositoryImpl() { super(Order.class); } @Override public List<Order> search(OrderSearch orderSearch) { QOrder order = QOrder.order; QMember member = QMember.member; JPQLQuery query = from(order); if (StringUtils.hasText(orderSearch.getMemberName())) { query.leftJoin(order.member, member) .where(member.name.contains(orderSearch.getMemberName())); } if (orderSearch.getOrderStatus() != null) { query.where(order.status.eq(orderSearch.getOrderStatus())); } return query.fetch(); }}
웹 애플리케이션 만들기에서 사용했던 주문 내역 검색 기능을 QuerydslRepositorySupport를 사용해 QueryDSL로 구현했다.
검색 조건에 따라 동적으로 쿼리를 생성한다.
생성자에서 QuerydslRepositorySupport에 엔티티 클래스 정보를 넘겨주어야 한다.
//QuerydslRepositorySupport의 핵심 기능@Repositorypublic abstract class QuerydslRepositorySupport{ //엔티티 매니저 반환 protected EntityManager getEntityManager() { return entityManager; } //from 절 반환 protected JPQLQuery<Object> from(EntityPath<?>... paths) { return querydsl.createQuery(paths); } //QueryDSL delete 절 반환 protected DeleteClause<JPADeleteClause> delete(EntityPath<?> path) { return new JPADeleteClause(entityManager, path); } //QueryDSL update 절 반환 protected UpdateClause<JPAUpdateClause> update(EntityPath<?> path) { return new JPAUpdateClause(entityManager, path); } //Querydsl을 편하게 사용하도록 돕는 헬퍼 객체 반환 protected Querydsl getQuerydsl() { return this.querydsl; }