-
QueryDSL으로 동적쿼리 작성하기JPA 2023. 9. 17. 00:01반응형
개요
조회쿼리를 작성해야 하는데 다음과 같은 요구사항이 있었습니다.
- 날짜를 저장하는 A칼럼, B칼럼이 존재한다.
- "A칼럼 조회", "B칼럼 조회"와 같은 Client의 입력으로 A칼럼 또는 B칼럼에 대해 특정기간에 해당하는 Entity를 조회한다.
동적 조건에 따라 2가지 케이스를 쿼리해야 합니다.
- A칼럼 조회가 들어오면 where 절에 A필드를 특정기간에 조회하는 쿼리
- B칼럼 조회가 들어오면 where 절에 B필드를 특정기간에 조회하는 쿼리
A칼럼 조회가 들어오면 where 절에 A필드를 특정기간에 조회하는 쿼리예시
select * from my_table WHERE A = BETWEEN 조회시작시간 AND 조회끝시간
B칼럼 조회가 들어오면 where 절에 B필드를 특정기간에 조회하는 쿼리
select * from my_table WHERE B = BETWEEN 조회시작시간 AND 조회끝시간
QueryDSL 활용
override fun selectDeliveryInfos(condition: Condition): List<DeliveryJpaEntity> { val delivery: QDeliveryJpaEntity = QDeliveryJpaEntity.deliveryJpaEntity return jpaQueryFactory.select(delivery) .where(betweenDateConditionType(condition)) .fetch() } private fun betweenDateConditionType(condition: Condition): BooleanExpression { val delivery: QDeliveryJpaEntity = QDeliveryJpaEntity.deliveryJpaEntity val dateType = when (condition.dateConditionType) { DateConditionType.INVOICE_REGISTERED_DATE -> delivery.invoiceRegisteredAt DateConditionType.ADMIN_CHECK_DATE -> throw UnsupportedOperationException("아직 미구현") DateConditionType.DELIVERY_COMPLETE_DATE -> throw UnsupportedOperationException("아직 미구현") } return dateType.between(condition.startDate, condition.endDate) }
이때 QueryDSL의 BooleanExpression을 활용하여 해결할 수 있습니다.
BooleanExpression은 where에서 사용할 수 있으며 null이 파라미터로 올 경우 조건문에서 제외합니다.
위의 쿼리문에서는 null은 직접적으로 활용하진 않았지만 이를 활용하여 송장번호가 등록된 날짜, 관리자가 확인한 날짜, 배송이 완료된 날짜로 WHERE 절을 만들어낼 수 있습니다.
테스트
@Test @Sql("classpath:delivery.sql") fun `배송처리일-기간조회(7월1일~8월20일) 수행하면 2개의 배송정보가 조회되어야 한다`(){ val condition = Condition( dateConditionType = DateConditionType.INVOICE_REGISTERED_DATE, startDate = LocalDateTime.of(2023,7,1,0,0,0).toInstant(ZoneOffset.UTC), endDate = LocalDateTime.of(2023,8,20,23,59,59).toInstant(ZoneOffset.UTC), ) val result = deliveryPersistenceAdapter.loadBy(condition = condition) result.deliveries.size shouldBe 2 }
임의로 N개의 데이터를 세팅하고 여기서 7월 10일, 8월 10일에만 invoiceRegisteeredAt 필드에 날짜를 지정하였습니다.
이후 테스트를 수행하면 N개의 데이터중 2개의 데이터만 조회되는 것을 확인할 수 있습니다.
반면에 해당하지 않는 과거의 날짜로 startDate, endDate를 설정하면 0개의 데이터가 조회됩니다.
참고자료
http://querydsl.com/static/querydsl/3.4.1/reference/ko-KR/html/ch03.html
https://jojoldu.tistory.com/394
'JPA' 카테고리의 다른 글
QueryDSL 페이징에 QuerydslPredicateExecutor 활용하기 (0) 2023.10.03 QueryDSL으로 페이징 구현하기 (0) 2023.09.18 JPA Persistable으로 성능최적화 해보기 (0) 2023.09.04 JPA 복합키 엔티티 (0) 2023.02.08 QueryDSL StringTemplate이란? (0) 2023.02.03