본문 바로가기

IT/JPA & Hibernate

[Hibernate] Spring Boot Querydsl 설정하기

1. Querydsl 이란?

JPA를 이용해서 복잡한 쿼리나 동적 쿼리를 작성할 경우 소스코드가 지저분해지는 경우가 많습니다.
이때 Querydsl 라이브러리를 이용해면 쿼리문자가 아니라 자바코드로 쿼리를 작성할 수 있습니다.

 

2. Querydsl의 장점

1. 자바코드로 쿼리를 작성하기 때문에 가독성이 좋아집니다.
2. 문법 오류를 컴파일 시점에서 잡아줍니다.
3. 동적 쿼리를 쉽게 만들 수 있습니다.

 

3. Querydsl 설정하기

테스트 환경은 다음과 같습니다. (버전을 모두 맞춰 주어야합니다!)
spring boot 2.2.2 RELEASE
maven
java 11
h2

1) pom.xml

...

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>4.1.4</version>
        </dependency>

        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>4.1.4</version>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
 ...
    
   <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <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>
...
querydsl-apt : Q클래스 생성 라이브러리입니다.
querydsl-jpa : querydsl 관련 라이브러리입니다.

apt-maven-plugin을 이용해서 target/generated-sources/java package에 엔티티 별로 Q클래스를 생성합니다.

 

2) src/main/resources/application.properties

spring.datasource.username=sa
spring.datasource.password=
spring.datasource.url=jdbc:h2:mem:mydb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.hikari.jdbc-url=jdbc:h2:mem:mydb
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
h2 database 설정 및 hibernate 설정을 해줍니다.

 

3) Member.java

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String account;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String name;

}
Member 엔티티를 정의하고 mvn package를 하면 target/generated-sources/java package에 엔티티 별로 Q클래스가 생성됩니다. 
Q클래스는 querydsl을 이용해 엔티티의 컬럼에 접근하거나 다양한 쿼리구문을 작성할 때 사용합니다. 

 

4) MemberTest.java

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Commit;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Transactional
@Commit
class MemberTest {

    @Autowired
    private EntityManager em;
    final String name = "member1";

    @BeforeEach
    public void setup(){
        Member member = Member.builder()
                .account("member@email.com")
                .name(name)
                .password("1234")
                .build();

        em.persist(member); // 미리 member를 생성한다.
    }

    @Test
    public void membersSearchTest() {
        JPAQueryFactory query = new JPAQueryFactory(em);
        QMember qMember = QMember.member;


        //querydsl을 이용해 java구문으로 query를 작성한다.
        Member member = query
                .select(qMember)
                .from(qMember)
                .where(qMember.name.eq(name))
                .fetchOne();

        assertEquals(member.getName(), name);
    }

}
Querydsl을 사용하려면 EntityManager객체를 생성자로 받은 JPAQueryFactory 객체가 필요합니다.
위 테스트를 진행하면 다음과 같은 쿼리가 DB로 전송됩니다.

---------------------------------------------------------
   select
        member0_.id as id1_0_,
        member0_.account as account2_0_,
        member0_.name as name3_0_,
        member0_.password as password4_0_ 
    from
        member member0_ 
    where
        member0_.name=?
---------------------------------------------------------