2024. 11. 20. 08:47ㆍSpring/QueryDSL
📁️ github 참고
https://github.com/kuk1157/spring-plus/commit/05cae3c4514c95331958ca1f9303da8c52a5985b
🛠️ 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가지 파일만 세팅하면된다.
※ 주의사항은 추후 트러블 슈팅 작성 후 링크 첨부하겠다.
@Repository
public interface TodoRepositoryCustom {
Optional<Todo> findByIdWithUserCustom(Long todoId);
}
- TodoRepositoryCustom파일 : TodoRepositoryImpl에서 사용할 쿼리메서드명을 임의로 지정해서 미리 생성해둔다.
- 이때 반환타입과 매개변수는 기존에 바꾸려고한 JPQL형태와 동일하게 맞춘다.
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문제도 해결이 되고, 결과가 잘 조회되는 것을 확인할 수 있다.
'Spring > QueryDSL' 카테고리의 다른 글
[21] Spring - 복잡한 쿼리 QueryDSL로 바꾸기 (0) | 2024.11.22 |
---|