JPA
QueryDSL으로 동적쿼리 작성하기
Junuuu
2023. 9. 17. 00:01
728x90
개요
조회쿼리를 작성해야 하는데 다음과 같은 요구사항이 있었습니다.
- 날짜를 저장하는 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