개발 메모장

[QueryDSL] QueryDSL 정의 및 설정방법 본문

ORM

[QueryDSL] QueryDSL 정의 및 설정방법

yyyyMMdd 2024. 1. 8. 17:58
728x90

#. JPA에 대해 찾아보다가 JPA로 구현이 어려운 내용을 처리하기 위해 같이 사용하는 라이브러리가 있습니다.

 

#. 일반 SQL과 비슷한 JPQL을 사용하기도 하나 타입 안전성, 가독성, 생산성, 재사용성을 높여주기에 QueryDSL을 주로 사용합니다.

 

#. QueryDSL은 ORM이 아닌 Java 기반의 라이브러리지만 JPA와 함께 사용한다는 점에서 ORM 카테고리에 글을 작성해 보겠습니다.


#. QueryDSL

    - Java에서 Type Safe SQL 유사 쿼리를 작성하기 위한 유연한 API를 제공하는 오픈소스 프레임워크입니다. 

    - 주로 Java에서 쿼리를 동적으로 구성하고 실행하는 데 사용되며 특히 정적 쿼리의 유연성이 부족해 사용이 번거롭거나 실행이 어려운 경우 더욱 빛을 발합니다.

    - JPA와 함께 사용하는 경우가 많습니다.


#. QueryDSL의 주요 기능

  1. 안전한 타입의 쿼리 제공

    - 개발자는 Java를 이용해 쿼리를 작성할 수 있으므로 잘못된 SQL 구문으로 인해 발생하는 런타임 오류 위험을 최소화할 수 있고 컴파일 시점에서 오류를 발견할 수 있게 됩니다.

  2. 가독성 및 생산성 좋은 API
    - 쿼리 구성을 위해 읽기 쉬운 API를 제공하므로 최소한의 코드로 복잡한 쿼리를 더 쉽게 작성할 수 있습니다.

  3. DBMS에 따른 방언에서 자유로움
    - 쿼리 구문을 변경하지 않고도 MySQL, PostgreSQL, Oracle, SQL Server 등과 같은 다양한 DBMS를 지원합니다.

  4. ORM 및 JPA와의 통합
    - Hibernate, JPA 등과 같은 ORM 프레임워크와 원활하게 통합되어 쿼리 기능을 향상시킬 수 있습니다.

  5. 코드 생성
    - 엔티티와 필드를 나타내는 Java 도메인별 클래스를 생성하는 코드 생성 기능을 제공해 컴파일 시간 확인 및 IDE 자동 완성을 가능하게 합니다.

#. QueryDSL의 장단점

  • 장점
    • 컴파일 과정에서 쿼리를 확인하기 때문에 런타임 오류를 줄여줍니다.
    • 유창한 API를 사용하여 간결하고 읽기 쉬운 쿼리 구성 가능
    • ORM 프레임워크와의 원활한 통합으로 복잡한 쿼리를 단순화할 수 있습니다.
    • SQL Injection 공격에 대한 위험이 보다 완화됩니다.

  • 단점
    • 통계성 쿼리의 경우 native 쿼리를 이용해 처리해야 합니다.
    • 사용을 위한 설정의 빌드도구와 플러그인에 대한 복잡함이 있고, 버전마다 처리하는 방법이 조금씩 다릅니다.
    • 생성된 Q 클래스는 엔티티 클래스에 변경 사항이 발생할 때마다 유지 및 관리가 필요합니다.

#. QueryDSL 사용을 위한 설정

 

  • 필자의 경우 codegen을 추가하지 않았을 때 com.querydsl.apt.jpa.JPAAnnotationProcessor을 찾지 못한다는 오류가 발생하여 라이브러리를 추가하였습니다.

  • 빌드도구, jpa 등의 버전에 따라 QueryDSL의 버전도 다르기 때문에 자신이 사용하는 것들의 버전 체크를 꼭 해주시길 바랍니다.

  • JPA(javax)

    - 아래와 같이 추가하고 Run as > maven clean > maven generate-sources를 실행해 주면 outputDirectory 태그 안의 폴더가 생성되고 그 내부에 @entity로 지정한 엔티티에 대한 Q파일이 생성됩니다.
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.mysema.codegen</groupId>
    <artifactId>codegen</artifactId>
    <version>0.6.8</version>
</dependency>


<plugin>
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
        </execution>
    </executions>
</plugin>

 


  • JPA(Jakarta)

    - 최신 버전의 경우 plugin 태그가 deprecated 되어 더 이상 사용하지 않습니다.
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>5.0.0</version>
    <classifier>jakarta</classifier>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>5.0.0</version>
    <classifier>jakarta</classifier>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-core</artifactId>
    <version>5.0.0</version>
</dependency>
<dependency>
    <groupId>com.mysema.codegen</groupId>
    <artifactId>codegen</artifactId>
    <version>0.6.8</version>
</dependency>

 


#. 사용 시 Bean 설정

  • QueryDSL을 사용하기 위해선 JPAQueryFactory를 이용하여 처리하는 경우가 많은데 이를 사용하기 위해선 EntityManager를 인스턴스로 넣어줘야 합니다

  • 이 과정을 bean으로 설정하여 전역에서 사용할 수 있게 처리하겠습니다.

  • QueryDSLConfig라는 클래스 파일을 생성하여 아래와 같이 작성하였습니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;

import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class QueryDSLConfig {
    @Autowired
    private final EntityManager em = null;

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

 


  • 사용할 때에는 아래와 같이 처리하면 됩니다.
private final JPAQueryFactory q;

    @GetMapping("qdsl")
    public JPAQuery<Integer> getMember2(@PathVariable("id") Long id) {
    	return jpaQueryFactory.selectOne()
        			.from()
              			.where();
    }

 

 

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================

728x90

'ORM' 카테고리의 다른 글

[QueryDSL] QueryDSL Projection  (0) 2024.02.01
[QueryDSL] QueryDSL 사용방법(2)  (1) 2024.01.31
[QueryDSL] QueryDSL 사용방법(1)  (1) 2024.01.30
[JPA] JPA의 정의와 사용 예제  (1) 2024.01.10
[myBatis] myBatis 사용방법  (1) 2023.12.26