개발 낙서장

[TIL] 내일배움캠프 50일차 - Query DSL 본문

Java/Sparta

[TIL] 내일배움캠프 50일차 - Query DSL

권승준 2024. 3. 7. 21:12

오늘의 학습 키워드📚

QueryDSL

QueryDSL은 기존 Spring Data JPA의 Query Method의 단점을 보완한 쿼리 방식이다.
기존 쿼리 메소드는 간단한 조회 등에는 직관적이고 사용하기 굉장히 편리했지만 조건이 복잡해질 수록 사용하기 까다로워진다.
또한 @Query를 통해 어느정도 커스텀 쿼리를 작성할 수 있다고 하지만 String 형식으로 작성하기에 개발자 입장에서 오타나 문법이 잘못된 부분을 파악하기 어렵다.

QueryDSL은 QueryFactory를 통해 Java 메소드로 쿼리를 구현할 수 있어 컴파일 단계까지 가지 않아도 오탈자, 잘못된 문법 등을 쉽게 파악할 수 있고 가장 큰 장점은 동적인 쿼리 작성에 매우 유연하다는 것이다.

적용 방법

먼저 의존성을 추가해준다. 스프링 버전에 따라 JDK 버전에 따라 방법은 상이하다.

	// queryDSL
	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"

 

이후 Configuration을 통해 JPAQueryFactory를 Bean으로 등록해 다른 클래스에서 주입이 가능하도록 해준다.

@Configuration
public class QueryDSLConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

Repository를 구성하는 방법은 먼저 QueryDSL에서 구현할 메소드들이 있는 Interface를 만들고 이를 구현하는 구현체를 만든다.
구현체에서 JPAQueryFactory를 주입받아 메소드를 구현하면 된다.

public interface UserRepositoryQueryDSL {

    User findByUserName(String userName);
}
@Repository
@RequiredArgsConstructor
public class UserRepositoryQueryDSLImpl implements UserRepositoryQueryDSL {

    private final JPAQueryFactory queryFactory;

    @Override
    public User findByUserName(String userName) {
        return queryFactory.selectFrom(user).where(user.userName.eq(userName)).fetchFirst();
    }
}
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryQueryDSL {

    Optional<User> findByEmail(String email);
}

이렇게 기존 Repository에서 방금 구현한 Interface를 상속하면 Service 구조를 바꾸지 않고 사용할 수 있다.

    @Test
    void findByUserName() {
        user = userRepository.save(new User("abc123@naver.com", "abc123", "abc123", UserRoleEnum.USER));
        String userName = "abc123";

        User findUser = userRepository.findByUserName(userName);

        assertNotNull(findUser);
        assertEquals(userName, findUser.getUserName());
    }

테스트 방법은 다른 Repository 테스트와 똑같다.

다만 주의해야할 점이 테스트용 Configuration을 만들어주어야 한다. 패키지 구조가 달라 적용되지 않는다.

@Configuration
public class TestQueryDSLConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

오늘의 회고💬

기존 CRUD를 개선하는 과정에서 복잡하고 어려운 기술들이 많은 것 같다.

 

내일의 계획📜

그냥 계속 하던 것을 열심히 해야 할 것 같다.

Comments