[18] Spring - QueryDSL 사용방법

2024. 11. 20. 08:47Spring/QueryDSL

728x90

📁️ github 참고

https://github.com/kuk1157/spring-plus/commit/05cae3c4514c95331958ca1f9303da8c52a5985b

 

refactor: 레벨 2_8 QueryDSL로 변경 · kuk1157/spring-plus@05cae3c

- gradle QueryDsl 의존성 추가 - JPAQueryFactory bean등록, Custom, Impl 파일 세팅 - Impl에서 QueryDSL 작성

github.com

 

🛠️ QueryDSL 사용방법

 

QueryDSL로 바꿀 코드)

-  해당 JPQL을 QueryDSL로 변경할 예정이다.

 

 

1. gradle 파일에 의존성 추가

    // QueryDSL
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"

- 버전은 본인의 springboot 버전과 확인해야한다.

 

2. build/clean, other/compileJava 파일 실행 - Q클래스 생성

※ Q클래스란 QueryDSL에서 쿼리를 작성할때 사용하는 객체를 자동으로 생성해준다. build에서 확인하면 각 entity에 Q를 접두어로 붙여서 생성이된다.

 

※ 자세한 설명

Q클래스는 QueryDSL을 사용할 때 쿼리를 안전하고 유연하게 작성할 수 있게 도와주는 중요한 도구입니다. Q클래스를 통해 타입 안전한 방식으로 쿼리를 작성하고, 다양한 조건을 동적으로 조합하여 쿼리를 실행할 수 있습니다. QueryDSL은 복잡한 쿼리를 다룰 때 매우 유용하며, 쿼리 작성 시 발생할 수 있는 오류를 컴파일 시점에 잡을 수 있어 디버깅이 쉬워집니다.

- gradle에서 캡쳐본에서 표시한 clean, compileJava를 더블클릭하여 실행한다.

 

3. config세팅(JPAQueryFactory, EntityManager 세팅)

@Configuration
public class JPAConfig {
    @PersistenceContext
    private EntityManager em;

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

EntityManager)

- EntityManager은 JPA에서 핵심적인 역할을 하는 인터페이스이며, 데이터베이스와 애플리케이션 간의 인터페이스 역할을 합니다. 간단히 말해서, JPA에서 엔티티 객체를 관리하고 저장/조회/수정/삭제하는 작업을 담당하는 객체입니다. 

-  @PersistenceContext는 EntityManager를 자동으로 주입할때 사용합니다.(영속성컨텍스트를 주입)

 

JPAQueryFactory)

- JPAQueryFactory는 QueryDSL에서 JPA를 사용하여 동적 쿼리를 생성하고 실행하는 데 필요한 핵심 클래스로, EntityManager를 통해 JPA 쿼리를 실행할 수 있게 해줍니다. JPAQueryFactory는 JPAQuery 객체를 생성하는 팩토리 클래스입니다.

 

4. Repository관련 파일 세팅

- 엔티티명Repository, 엔티티명RepositoryCustom, 엔티티명RepositoryImpl 세팅

 

※ 엔티티명Repository는 이미 존재하기 때문에 Custom과 Impl 2가지 파일만 세팅하면된다.

※ 주의사항은 추후 트러블 슈팅 작성 후 링크 첨부하겠다.

TodoRepositoryCustom

@Repository
public interface TodoRepositoryCustom {
    Optional<Todo> findByIdWithUserCustom(Long todoId);
}

- TodoRepositoryCustom파일 : TodoRepositoryImpl에서 사용할 쿼리메서드명을 임의로 지정해서 미리 생성해둔다.

- 이때 반환타입과 매개변수는 기존에 바꾸려고한 JPQL형태와 동일하게 맞춘다.

 

TodoRepositoryImpl

import static org.example.expert.domain.todo.entity.QTodo.todo;
import static org.example.expert.domain.user.entity.QUser.user;

@Repository
@RequiredArgsConstructor
public class TodoRepositoryImpl implements TodoRepositoryCustom {
    private final JPAQueryFactory queryFactory;
    @Override
    public Optional<Todo> findByIdWithUserCustom(Long todoId){
        return Optional.ofNullable(queryFactory
            .selectFrom(todo)
            .join(todo.user, user).fetchJoin()
            .where(todo.id.eq(todoId))
            .fetchOne());
    }
}

- TodoRepositoryCustom에서 만들어둔 쿼리메소드명과 동일하게 맞춰서 QueryDSL을 사용한다.

- selectFrom에서 엔티티명(테이블명)을 입력하여 조회한다.

- 기존코드에서 user와 JOIN FETCH을 하고 있기 때문에 join(), fetchJoin()을 활용한다.

※ 이때 todo와 user는 Q클래스를 가져와서 각 조건절에 맞게 넣어준다.

- 상단에 Q클래스 todo, user를 import 하고 있는 것을 볼 수 있다.

- where절에도 필요한 것을 넣어 조건을 걸어준다.

- 이 형태로 바꿔주면 최종으로 JPQL대신 해당 코드로 변경할 수 있다.

 

Todo todo = todoRepository.findByIdWithUserCustom(todoId) // 2_8 QueryDSL로 변경한 커스텀쿼리메서드
.orElseThrow(() -> new InvalidRequestException("Todo not found"));

- 서비스단에서 변경한 쿼리메서드로 적용

- 최종 쿼리를 확인해보면 정상적으로 Join이 되어 N+1문제도 해결이 되고, 결과가 잘 조회되는 것을 확인할 수 있다. 

 

 

 

 

728x90

'Spring > QueryDSL' 카테고리의 다른 글

[21] Spring - 복잡한 쿼리 QueryDSL로 바꾸기  (0) 2024.11.22