ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • QueryDSL 페이징에 QuerydslPredicateExecutor 활용하기
    JPA 2023. 10. 3. 00:01
    728x90

    QuerydslPredicateExecutor란?

    Predicate 인스턴스를 실행할 수 있도록 spring data에서 지원하는 인터페이스입니다.

    반환값들을 보면 Page<T>로 Predicate를 통해 페이징 된 결과를 받을 수 있습니다.

    인터페이스의 네이밍을 보았을 때 Predicate를 기반으로 실행한다!라고 이해할 수 있습니다.

     

    Predicate란?

    Predicate를 직역하면 서술어라는 의미를 가집니다.

    간단하게는 where 절에 들어가는 조건문을 뜻합니다.

    BooleanBuilder, BooleanExpression이 Predicate 인터페이스를 구현하고 있습니다.

     

    사용법

    QuerydslPredicateExecutor 인터페이스 상속받기

    @Repository
    interface DeliveryJpaRepository : JpaRepository<DeliveryJpaEntity, UUID>,
      CustomDeliveryJpaRepository, QuerydslPredicateExecutor<DeliveryJpaEntity> {
    
    }

     

     

    Adapter 부분 구현

      fun loadNeedToReadyDeliveries(page: Int, size: Int, productId: Long?): Page<Delivery> {
        val booleanExpression = generateLoadNeedToReadyDeliveriesPredicate(productId)
    
        val pageable = PageRequest.of(page - 1, size, Sort.by("expectedDeliveryAt"))
        return deliveryJpaRepository.findAll(booleanExpression, pageable)
          .map { it.toDomainEntity() }
      }
    
      private fun generateLoadNeedToReadyDeliveriesPredicate(productId: Long?): Predicate {
        val qDelivery: QDeliveryJpaEntity = QDeliveryJpaEntity.deliveryJpaEntity
        return qDelivery.deliveryStatus
          .eq(DeliveryStatus.WAITING)
          .and(qDelivery.expectedDeliveryAt.isNotNull)
          .and(productId(productId))
      }
    
      private fun productId(productId: Long?): BooleanExpression?{
        val qDelivery: QDeliveryJpaEntity = QDeliveryJpaEntity.deliveryJpaEntity
        if(productId == null){
          return null
        }
        return qDelivery.productId.eq(productId)
      }

    booleanExpression을 활용하여 쿼리를 구성합니다, 이때 동적쿼리를 활용할 수 있습니다.

    이후에는 page, size를 기반으로 Pageable 객체를 만들어냅니다

    이후에는 간편하게 findAll을 사용하여 booleanExpression, pageable 객체를 넘겨주고, domainEntity로 반환하여 Service로 던져줍니다.

     

    사용해 보면서 느낀 장점

    • Predicate와 Pageable 객체만 넘기면 손쉽게 페이징 구현이 가능하다.

     

    사용해 보면서 느낀 단점 (Predicate만 넘길 수 있음)

    • group by 불가능
    • join 불가능

     

    즉, 조금 복잡한 케이스에 사용할 수 없다.

    이런 경우에는 순수하게 쿼리를 작성하는 방법을 선택했다.

     

     

     

    참고자료

    http://querydsl.com/static/querydsl/3.7.2/reference/ko-KR/html/ch03.html

    https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/querydsl/QuerydslPredicateExecutor.html

     

    댓글

Designed by Tistory.