JPA

QueryDSL 페이징에 QuerydslPredicateExecutor 활용하기

Junuuu 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