QueryDSL 테스트

남예준·2025년 11월 20일

제대로 배운 것은 아니고 잠깐 프로젝트에서 사용을 해본 것을 기록해봤다.

먼저 gradle 의존성을 추가해준다.

	implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
	annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
	annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
	annotationProcessor 'jakarta.persistence:jakarta.persistence-api'

그 다음에 ./gradlew clean compileJava 를 입력하면 ./build/generated/sources/annotationProcessor/java/main/ 위치에 Q class가 생기게 된다.

그 다음에 QueryDSL Config를 작성해줘야 한다. JPAQueryFactory를 주입해줄 수 있도록 하는 것이다.

그럼 QueryDSL 을 사용할 준비는 끝난 것이다.

그리고 코드를 작성하면 다음과 같아진다.

UserRepository를 interface로 만들어서 기능에 필요한 애들을 메소드 시그니처로 작성해놓고 구현체에 JPA를 쓸 건지 QueryDSL을 쓸 건지 선택해서 Override하는 형태이다.

@Component
@RequiredArgsConstructor
public class UserRepositoryAdapter implements UserRepository {

    private final JpaUserRepository jpaUserRepository;
    private final JPAQueryFactory queryFactory;

    @Override
    public User save(User user) {
        return jpaUserRepository.save(user);
    }

    @Override
    public User findById(Long id) {
        return jpaUserRepository.findById(id).orElseThrow(
            () -> new BusinessException(ErrorCode.USER_NOT_FOUND)
        );
    }

    @Override
    public User findByName(String name) {
        return jpaUserRepository.findByName(name).orElseThrow(
            () ->  new BusinessException(ErrorCode.USER_NOT_FOUND)
        );
    }

    @Override
    public boolean existsByName(String name) {
        return jpaUserRepository.existsByName(name);
    }

    @Override
    public Integer findMaxDriverOrderByHubId(UUID hubId) {
        Integer result = queryFactory
            .select(driver.order.max().coalesce(0))
            .from(user)
            .join(user.driver, driver)
            .where(driver.hubId.eq(hubId))
            .fetchOne();

        return result != null ? result : 0;
    }

    @Override
    public Integer findMaxHubDriverOrder() {
        Integer result = queryFactory
            .select(driver.order.max().coalesce(0))
            .from(user)
            .join(user.driver, driver)
            .where(driver.hubId.isNull())
            .fetchOne();

        return result != null ? result : 0;
    }

    public void delete(User user, Long requesterId) {
        user.markDeleted(requesterId);
    }
}

원래 JPA 코드

    // index 생성 예정 : hub_id, order
    @Query("""
        select coalesce(max(d.order), 0)
        from User u
        join u.driver d
        where d.hubId = :hubId
    """)
    Integer findMaxDriverOrderByHubId(@Param("hubId") UUID hubId);

    @Query("""
        select coalesce(max(d.order), 0)
        from User u
        join u.driver d
        where d.hubId is null
    """)
    Integer findMaxHubDriverOrder();

이후 코드

    @Override
    public Integer findMaxDriverOrderByHubId(UUID hubId) {
        Integer result = queryFactory
            .select(driver.order.max().coalesce(0))
            .from(user)
            .join(user.driver, driver)
            .where(driver.hubId.eq(hubId))
            .fetchOne();

        return result != null ? result : 0;
    }

    @Override
    public Integer findMaxHubDriverOrder() {
        Integer result = queryFactory
            .select(driver.order.max().coalesce(0))
            .from(user)
            .join(user.driver, driver)
            .where(driver.hubId.isNull())
            .fetchOne();

        return result != null ? result : 0;
    }

뭔가 이해하기 쉽고 간결한 코드 작성이 된다고 생각한다.

0개의 댓글