QueryDSL을 사용하면 복잡한 쿼리를 Java로 표현가능하며 동적인 쿼리도 작성이 가능하다. 기존의 복잡한 쿼리들을 JPQL이나 native query로 작성하였는데 이번 프로젝트를 진행하면서 JPA와 QueryDSL을 적용하려 한다.
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
...
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
...
}
dependencies {
...
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
...
}
/*
* queryDSL 설정 추가
*/
// querydsl에서 사용할 경로 설정
def querydslDir = "$buildDir/generated/querydsl"
// JPA 사용 여부와 사용할 경로를 설정
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
// build 시 사용할 sourceSet 추가
sourceSets {
main.java.srcDir querydslDir
}
// querydsl 컴파일시 사용할 옵션 설정
compileQuerydsl{
options.annotationProcessorPath = configurations.querydsl
}
// querydsl 이 compileClassPath 를 상속하도록 설정
configurations {
compileOnly {
extendsFrom annotationProcessor
}
querydsl.extendsFrom compileClasspath
}
@Configuration
public class QuerydslConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
QueryDSL을 사용하기 위해 JPAQueryFactory에 bean으로 등록하고 구현체에서 이를 사용하여 쿼리를 생성한다.
gradle에서 compile.java를 실행하면 다음과 같이 build 폴더내에 Q 객체들이 생성된다.
해당 경로는 build.gradle에서 설정한 qeurydslDir로 세팅할 수 있다.
Spring Data JPA와 같이 사용하기 위해선 다음과 같은 구조가 확장성에도 좋고 OCP, DIP 원칙에 부합한다.
public interface BoardRepositoryCustom {
Page<Board> findAllByMemberId(long memberId, Pageable pageable);
}
@Repository
@RequiredArgsConstructor
public class BoardRepositoryImpl implements BoardRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
@Override
public Page<Board> findAllByMemberId(long memberId, Pageable pageable) {
List<Board> content = jpaQueryFactory
.select(board)
.from(board)
.leftJoin(board.member, member)
.on(member.memberId.eq(memberId))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
return new PageImpl<>(content, pageable, content.size());
}
}
내가 작성한 게시글을 조회하는 기능(페이지네이션)을 구현하기 위한 쿼리이다.
@Repository
public interface BoardRepository extends JpaRepository<Board, Long>, BoardRepositoryCustom {
}