QueryDSL
QueryDSL은 JPA 표준에서 지원하는 Criteria 기술처럼 JPQL 빌더 역할을 해주는 오픈소스 프로젝트이다. 기존의 JPQL처럼 문자로 작성하는 것이 아닌 자바 코드로 JPQL을 작성할 수 있도록 해주어 문법 오류를 컴파일 단계에서 잡을 수 있고 IDE의 자동완성 기능의 도움을 받을 수 있는 등 여러가지 장점이 있다. 또한 Criteria에 비해 복잡성이 낮다. 쿼리를 문자가 아닌 코드로 작성해도 쉽고 간결하며 그 모양도 쿼리와 비슷하게 개발할 수 있게 해준다.
QueryDSL 설정
필자는 프로젝트 설정 시 메이븐을 주로 사용하기에 메이븐을 위주로 설정 방법을 다루겠다.
먼저 pom.xml에 다음과 같이 의존성을 추가한다.
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
- querydsl-jpa: QueryDSL JPA 라이브러리
- querydsl-apt: 쿼리 타입(Q)을 생성할 때 필요한 라이브러리
- Spring Boot로 프로젝트 구성 시, 위의 의존성 또한 Spring Boot가 안정적인 버전을 알아서 설정 해주기 때문에 version을 기입하지 않아도 된다!
QueryDSL을 사용하려면 Criteria의 메타 모델처럼 엔티티를 기반으로 쿼리 타입이라는 쿼리용 클래스를 생성해야 한다. 다음과 같이 쿼리 타입 생성용 APT 플러그인을 메이븐에 설정한다.
<project>
<build>
<plugins>
...
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
</project>
- JPAAnnotationProcessor는 javax.persistence.Entity 애노테이션을 가진 도메인 타입을 찾아서 쿼리 타입을 생성한다.
- 도메인 타입으로 Hibernate 애노테이션을 사용하면, APT 프로세서로 com.querydsl.apt.hibernate.HibernateAnnotationProcessor를 사용해야 한다.
- mvn clean install 을 실행하면, target/generated-sources/java 디렉토리에 Query 타입이 생성된다.
- 이클립스를 사용할 경우, mvn eclipse:eclipse 를 실행하면 target/generated-sources/java 디렉토리가 소스 폴더에 추가된다.
- 생성된 Query 타입을 이용하면 JPA 쿼리 인스턴스와 쿼리 도메인 모델 인스턴스를 생성할 수 있다.
참고! QEntity가 생기는 경로는 gitignore 설정하는 것을 권장한다. 메이븐이 알아서 생성해 주는 파일이기 때문에 프로젝트 설정에 따라 알아서 생성된다. 라이브러리 사용에 따라 변경될 수 있는 부분이기 때문에 git에 올리지 말고 빌드 해서 새로 생성하여 쓰는 것이 올바르다.
QueryDSL 검증해보기
자 이제 QueryDSL을 사용하기 위한 설정이 끝났다. 간단한 엔티티와 함께 테스트 코드를 짜보도록 하겠다.
참고! 필자의 테스트 환경은 2.4.2버전의 스프링부트로 spring-boot-starter-data-jpa 의존성과 H2 데이터베이스를 사용하여 프로젝트 환경을 구성하였다.
- 예제 엔티티 구현
@Entity
@Getter @Setter
public class Hello {
@Id @GeneratedValue
private Long id;
}
엔티티를 구현했다면 target/generated-sources/java에 Q타입을 생성하도록 하자. 생성 방법은 위에 기재해놨다.
- 검증 테스트 코드 작성
@SpringBootTest
@Transactional
class QuerydslinfdemoApplicationTests {
@PersistenceContext
EntityManager em; // 1
@Test
void contextLoads() {
Hello hello = new Hello();
em.persist(hello);
JPAQueryFactory query = new JPAQueryFactory(em); // 2
QHello qHello = new QHello("h"); // 3
Hello result = query
.selectFrom(qHello)
.fetchOne();
assertThat(result).isEqualTo(hello);
assertThat(result.getId()).isEqualTo(hello.getId());
}
}
- EntityManager: Spring Boot가 자동으로 생성한 JPA의 EntityManager를 주입 받았다.
- JPAQueryFactory 생성시 EntityManager 객체를 주입하여 생성한다.
- 쿼리 타입(Q)은 위와 같이 JPQL의 별칭 역할을 하는 값을 넣어주어 인스턴스를 생성한다.
쿼리 타입(Q)는 사용의 편리성을 위해 기본 인스턴스를 보관하고 있어 다음처럼 사용할 수도 있다.
QHello qHello = QHello.hello;
주의! 같은 엔티티를 조인하거나 같은 엔티티를 서브쿼리에 사용할 때는 별도의 별칭을 사용해야 된다.
위의 테스트 코드가 잘 통과하는 것이 확인되면 QueryDSL의 설정이 끝난 것이다.
Hello result = query
.selectFrom(qHello)
.fetchOne();
위와 같이 QueryDSL로 쿼리를 생성하여 사용하면 실제로는 아래와 같은 JPQL이 실행된다.
"select m from Member m"
간단한 예제를 다루었지만 QueryDSL의 장점을 확실히 느낄 수 있을 것이다. 엔티티의 요소가 변경된다거나 오타가 난다거나하면 기존에 문자열로 작성하였던 JPQL과는 달리 컴파일 시점에서 오류를 찾을 수 있고, IDE의 자동완성 도움을 받아 쿼리를 간편하게 생성할 수 있다. 또한 동적 쿼리 기능도 편리하고 간결하게 짤 수 있도록 지원을 한다. 여러가지로 객체 지향의 기술로 쿼리를 짤 수 있게 된다는 큰 강점이 있다.
향후에는 QueryDSL의 기본문법들과 추가적인 기능들을 정리하여 포스팅할 예정이다.
참고
Query Reference Guide: http://www.querydsl.com/static/querydsl/4.4.0/reference/html/ch02.html#d0e137
'Study > spring' 카테고리의 다른 글
QueryDSL(3) - 프로젝션, distinct, 동적 쿼리, 벌크 연산 (0) | 2021.01.26 |
---|---|
QueryDSL(2) - 쿼리 생성 방법, 기본 문법 (0) | 2021.01.25 |
Spring Data JPA(2) - JpaRepository 쿼리 메소드 기능 (0) | 2021.01.20 |
Spring Data JPA(1) - Spring Data JPA와 JpaRepository 인터페이스의 공통 기능 (0) | 2021.01.20 |
JPA - OSIV(Open Session In View) 정리 (18) | 2021.01.18 |