1. JPQL
JPQL(Java Persistence Query Language)을 사용하면 @Query 주석을 사용하여 Repository에서 직접 쿼리를 정의할 수 있다. 또한 선택적으로 동적 매개변수를 위해 @Param과 결합할 수 있다.
예시) '제품' 엔티티가 있고 '이름' 및 '카테고리'를 기준으로 제품을 필터링한다고 가정
@Repositorypublic interface ProductRepository extends JpaRepository<Product, Long> {
@Query("SELECT p FROM Product p WHERE (:name IS NULL OR p.name = :name) AND (:category IS NULL OR p.category = :category)")
List<Product> findProducts(@Param("name") String name, @Param("category") String category);
}
// 사용 예시
List<Product> products = productRepository.findProducts("Laptop", "Electronics");
장점:
- 간단한 쿼리를 작성하고 이해하기 쉽다.
- 추가 설정이나 종속성이 필요하지 않다.
단점:
- 쿼리 복잡성이 증가함에 따라 관리 및 확장이 어렵다.
- 제한된 유형의 안전성과 재사용성.
- String으로 작성한 코드로, 메서드가 실행되기 전까지 에러를 찾을 수 없다.
2. QueryDSL
QueryDSL은 Java에서 유형이 안전한 SQL과 유사한 쿼리를 작성하기 위한 유연한 API를 제공한다.
통계나 서브 쿼리등 복잡한 쿼리를 작성해야 할 때 사용할 수 있다.
// where 조건이 많은 경우에 booleanbuilder를 적용하여 사용
@RequiredArgsConstructor
public class OrderRepositoryCustomImpl implements OrderRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
QOrderEntity orderEntity = QOrderEntity.orderEntity;
QOrderDetailEntity orderDetailEntity = QOrderDetailEntity.orderDetailEntity;
@Override
public Page<OrderSearchResponseDto> searchOrders(OrderType orderType, UUID menuId, Pageable pageable) {
BooleanBuilder predicate = new BooleanBuilder();
predicate.and(orderEntity.deletionStatus.eq(DeletionStatus.ACTIVE));
if (orderType != null) {
predicate.and(orderEntity.orderType.eq(orderType));
}
if (menuId != null) {
predicate.and(orderDetailEntity.menu.id.eq(menuId));
}
JPAQuery<OrderSearchResponseDto> query = jpaQueryFactory
.select(new QOrderSearchResponseDto(orderEntity))
.leftJoin(orderEntity.orderDetailList, orderDetailEntity)
.where(predicate)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());
...
...
}
}
장점:
- Q객체를 통해 마치 sql을 작성하는 것처럼 쿼리를 작성할 수 있다.
- 문자열 기반 쿼리 대신 Java 코드를 사용하므로 리팩토링 쉽다.
- 통계나 서브 쿼리등 복잡한 쿼리를 작성해야 할 때 유용하다.
- 동적이고 복잡한 쿼리를 작성할 수 있다.
단점:
- QueryDSL API에 대한 지식
- : Q 클래스(예: qUser) 생성이 필요하므로 빌드 프로세스가 복잡해질 수 있다.
정리
단순 및 정적 쿼리의 경우
@Query가 포함된 JPQL을 선호한다. 간단하여 이해하기 쉽다.
쿼리가 단순하고 변경될 가능성이 없을 때 효과적이다.
@Query("SELECT p FROM Product p WHERE p.name = :name")
List<Product> findByName(@Param("name") String name);
동적, 복잡, 유지 관리 가능한 쿼리가 필요한 경우 QueryDSL
'Spring' 카테고리의 다른 글
| Spring Day 36 : RuntimeException 과 IllegalArgumentException (0) | 2024.03.25 |
|---|---|
| Spring Day 35 : 동시성 제어의 중요성 (0) | 2024.03.22 |
| Spring Day 34 : @Cacheable, @CachePut, @CacheEvict (0) | 2024.03.20 |
| Spring Day 33 : 메서드 실행 시간 측정 기능 AOP (0) | 2024.03.15 |
| Spring Day 32 : Booleanbuilder, Booleanexpression (0) | 2024.03.12 |