집돌이 공대남 IT

JPA 프로그래밍 마스터하기: 중급부터 전문가까지 실습을 통한 학습(5) 본문

IT/웹개발

JPA 프로그래밍 마스터하기: 중급부터 전문가까지 실습을 통한 학습(5)

집공이 2023. 9. 2. 12:00

JPA 활용 전략 및 최적화 기법: 동적 쿼리 작성과 QueryDSL

안녕하세요, 여러분! 집돌이 공대남입니다.

지난 시간에 이어, 이번 포스트에서는 JPA와 QueryDSL을 활용하여 동적 쿼리를 작성하는 방법에 대해 알아보도록 하겠습니다.

동적 쿼리의 필요성

먼저, 동적 쿼리가 필요한 이유에 대해 간략하게 설명하겠습니다. 웹 애플리케이션에서는 사용자의 요청에 따라 다양한 형태의 데이터를 반환해야 합니다. 사용자의 검색 조건에 따라 결과를 필터링하거나 정렬해야 하는 경우가 많죠. 이럴 때 매번 쿼리를 작성하는 것은 매우 비효율적입니다. 이런 문제를 해결하기 위해 동적 쿼리를 사용합니다.

 

JPA와 QueryDSL 사용법

JPA는 JPQL이라는 쿼리 언어를 제공합니다. 하지만, 동적 쿼리를 작성할 때는 JPQL의 문법이 복잡하고 가독성이 떨어질 수 있습니다. 그래서 보다 편리하게 동적 쿼리를 작성하기 위해 QueryDSL 라이브러리를 사용하는 것이 일반적입니다.

QueryDSL은 JPA Criteria를 기반으로 하는데, 타입 세이프하며 쿼리의 구조를 컴파일 시점에 체크할 수 있다는 장점이 있습니다.

아래는 QueryDSL을 사용하여 동적 쿼리를 작성하는 간단한 예제입니다.

public class BookRepositoryCustomImpl implements BookRepositoryCustom {
    @PersistenceContext
    private EntityManager em;

    @Override
    public List<Book> find(BookSearchCondition condition) {
        JPAQueryFactory query = new JPAQueryFactory(em);
        QBook book = QBook.book;

        BooleanBuilder builder = new BooleanBuilder();

        if (StringUtils.hasText(condition.getTitle())) {
            builder.and(book.title.contains(condition.getTitle()));
        }

        if (condition.getGenre() != null) {
            builder.and(book.genre.eq(condition.getGenre()));
        }

        if (condition.getPriceGoe() != null) {
            builder.and(book.price.goe(condition.getPriceGoe()));
        }

        if (condition.getPriceLoe() != null) {
            builder.and(book.price.loe(condition.getPriceLoe()));
        }

        return query.selectFrom(book)
                     .where(builder)
                     .fetch();
    }
}

위 코드에서는 BooleanBuilder를 사용하여 동적으로 where 절을 구성하고 있습니다. StringUtils.hasText()를 사용하여 문자열이 null이 아니고 길이가 0보다 큰지 검사하고, builder.and()를 사용하여 조건을 추가합니다. 마지막으로 query.selectFrom().where().fetch()를 통해 쿼리를 실행하고 결과를 가져옵니다.

이처럼 QueryDSL을 활용하면 복잡한 동적 쿼리도 코드로 쉽게 표현할 수 있습니다.

다음 포스트에서는 이렇게 작성한 동적 쿼리를 활용하여 실제 애플리케이션에서 데이터를 조회하는 방법에 대해 알아보겠습니다. 감사합니다.