- 타입 안전한 동적 쿼리를 직관적으로 작성할 수 있게 도와주는 Java 기반 쿼리 라이브러리
환경세팅
- build.gradle
dependencies {
// 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"
}
- QueryDslConfig.java
@Configuration
class QueryDslConfig {
@PersistenceContext
private EntityManager em;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(JPQLTemplates.DEFAULT, em);
}
}
- Entity 클래스의 메타 정보를 담고 있는 클래스
- 타입 안정성(Type safe)을 보장하면서 쿼리를 작성할 수 있음
- 컴파일 시점에 쿼리 오류를 확인할 수 없는 JPQL의 단점 보완
TodoRepository
TodoRepository 를 JpaRepository 와 TodoQueryRepository 를 다중상속 받게 함으로서, 기존의 JPA, JPQL 에 추가로 QueryDSL 을 사용할 수 있도록 하였다.
TodoQueryRepository
public interface TodoQueryRepository {
Todo findByIdByDsl(long todoId);
}
TodoQueryRepositoryImpl
TodoQueryRepository 를 상속받는 구현체를 만들었다.
수동으로 @Repository 어노테이션을 달아서 지정해줘야하고 JPAQueryFactory 를 가져오고 생성자를 만들어준다.
@Repository
@RequiredArgsConstructor
public class TodoQueryRepositoryImpl implements TodoQueryRepository{
private final JPAQueryFactory queryFactory;
@Override
public Todo findByIdByDsl(long todoId) {
return queryFactory
.select(todo)
.from(todo)
.join(todo.user, user).fetchJoin()
.join(todo.comments, comments)
.where(
todoIdEq(todoId)
).fetchOne();
}
private BooleanExpression todoIdEq(Long todoId) {
return todoId != null ? todo.id.eq(todoId) : null;
}
}
todoId 로 todo 를 조회하는 메서드
join(todo.user, user):
- todo.user: Todo 엔티티와 연관된 User 엔티티를 지정함. 이는 @ManyToOne 관계로 설정되어 있습니다.
- user: 조인할 User 엔티티의 별칭입니다. 이 별칭은 후속 쿼리에서 User에 접근하는 데 사용됨.
- 간단하게 todo 와 user 를 연결한다고 생각하면 된다.
fetchJoin()
- 지연 로딩(LAZY)을 무시하고 즉시 로딩(EAGER)처럼 연관된 User 데이터를 한 번에 가져오도록 강제함.
- 즉, Todo 엔티티를 조회할 때 User 엔티티도 함께 조회됩니다.
todo 와 user, todo 와 comments 모두 일대다 관계이기 때문에 둘 다 fetchJoin() 을 걸 수는 없다.
만약 하나가 일대일 관계였으면 걸 수 있다.
그렇기 때문에 comments 는 직접 Todo Entity 로 들어가서 BatchSize 옵션을 넣어줘야한다.
Todo
@BatchSize(size = 10)
@OneToMany(mappedBy = "todo", cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
'컴퓨터 프로그래밍 > Spring' 카테고리의 다른 글
[Spring] Projection 및 예시코드 설명 (0) | 2024.10.07 |
---|---|
[Spring] Spring Security (0) | 2024.10.04 |
[Spring] Lazy Loading 과 Eager Loading 의 차이, N+1 Problem 과 해결 방법 (1) | 2024.10.03 |
[Spring] Password Encoder 사용법 (0) | 2024.09.29 |
[Spring] OAuth2.0 Kakao 소셜 로그인 기능 구현 (0) | 2024.09.29 |