[SpringBoot] Spring Boot 3 버전 이후 gradle에 querydsl 사용 환경 설정하기
안녕하세요. J4J입니다.
이번 포스팅은 spring boot 3 버전 이후 gradle에 querydsl 사용 환경 설정하는 방법에 대해 적어보는 시간을 가져보려고 합니다.
관련 글
[SpringBoot] JPA에서 QueryDSL 사용하기
[SpringBoot] QueryDSL Projections로 결과값 핸들링하기
들어가기에 앞서
Spring Boot의 3버전이 등장하면서 최근에 생성되는 많은 프로젝트들은 3 버전 이상의 환경들을 구성하고는 합니다.
3 버전부터는 3 버전 이전과 설정하는 방법이 달라지기도 하고, 3 버전 이상의 환경에서 설정하는 방법을 더 궁금해하실 것 같아서 querydsl 사용 환경 설정하는 방법만 따로 정리하려고 합니다.
querydsl이 무엇인지에 대해 더 궁금하신 분들은 관련 글에 있는 링크들을 참고해주시면 됩니다.
gradle에서 querydsl 사용 환경 설정 방법
전체적인 흐름을 파악하기 쉽게 DB 테이블 생성부터 DB 설정 및 JPA 설정까지 모두 작성해 보겠습니다.
사용하는 DB는 mysql이니 참고 부탁드립니다.
[ 1. DB 테이블 생성 ]
create table student (
no bigint auto_increment primary key,
name varchar(200),
age int,
create_id varchar(50),
create_at datetime,
update_id varchar(50),
update_at datetime
);
[ 2. properties 설정 ]
// application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver # DB driver
url: jdbc:mysql://localhost:3306/querydsl?serverTimezone=UTC # DB url
username: username # DB 계정 username
password: password # DB 계정 password
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect # 고유하게 사용할 DB dialect
show_sql: true # console에 실행되는 sql 출력
format_sql: true # sql 출력 시 보기 쉽게 format 수행
[ 3. build.gradle 설정 ]
// build.gradle
dependencies {
// jpa
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// mysql
runtimeOnly 'com.mysql:mysql-connector-j'
// 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"
}
// querydsl generated 경로 설정
def querydslDir = "build/generated/querydsl"
tasks.withType(JavaCompile) {
options.generatedSourceOutputDirectory = file(querydslDir)
}
clean {
delete file(querydslDir)
}
[ 4. querydsl config 클래스 추가 ]
package com.jforj.querydsl.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
public class QuerydslConfig {
private final EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
[ 5. DB entity 클래스 추가 ]
package com.jforj.querydsl.entity;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "student")
public class StudentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long no;
private String name;
private int age;
private String createId;
private LocalDateTime createAt;
private String updateId;
private LocalDateTime updateAt;
@Builder
public StudentEntity(String name, int age, String createId, String updateId) {
this.name = name;
this.age = age;
this.createId = createId;
this.createAt = LocalDateTime.now();
this.updateId = updateId;
this.updateAt = LocalDateTime.now();
}
}
[ 6. dto 클래스 추가 ]
package com.jforj.querydsl.dto;
import lombok.Getter;
import lombok.ToString;
@ToString
@Getter
public class StudentInfoDto {
private String name;
private int age;
}
[ 7. repository 클래스 추가 ]
// JPARepository
package com.jforj.querydsl.repository;
import com.jforj.querydsl.entity.StudentEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentJpaRepository extends JpaRepository<StudentEntity, Long> {
}
// Repostiory
package com.jforj.querydsl.repository;
import com.jforj.querydsl.dto.StudentInfoDto;
import com.jforj.querydsl.entity.StudentEntity;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
import static com.jforj.querydsl.entity.QStudentEntity.studentEntity;
@Repository
@RequiredArgsConstructor
public class StudentRepository {
private final JPAQueryFactory jpaQueryFactory;
private final StudentJpaRepository studentJpaRepository;
public void createStudent(String name, int age) {
studentJpaRepository
.save(
StudentEntity
.builder()
.name(name)
.age(age)
.createId("createId")
.updateId("updateId")
.build()
);
}
public List<StudentInfoDto> selectStudentInfo() {
return jpaQueryFactory
.select(
Projections
.fields(
StudentInfoDto.class,
studentEntity.name,
studentEntity.age
)
)
.from(studentEntity)
.fetch();
}
}
테스트
위와 같이 생성한 DB 구조에 맞게 설정을 모두 완료했다면 올바르게 동작하는지 테스트해보겠습니다.
다음과 같이 테스트 코드를 구성한 뒤 실행해 보면 올바르게 querydsl이 수행되는 것을 확인할 수 있습니다.
package com.jforj.querydsl.repository;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@Slf4j
class StudentRepositoryTest {
@Autowired
private StudentRepository studentRepository;
@Test
void createStudent() {
studentRepository.createStudent("test name", 100);
}
@Test
void selectStudentInfo() {
log.info(
studentRepository.selectStudentInfo().toString()
);
}
}
querydsl 실행 query parameter 확인하기
위의 설정에서 student entity를 생성하는 테스트를 수행해 보면 시스템 로그에 다음과 같이 실행된 query가 보이는 것을 확인할 수 있습니다.
해당 로그만 확인해 봤을 때 크게 문제 될 건 없어 보이지만 query가 동작되는 동안 필요한 parameter 정보들을 확인할 수 없는 불편함을 겪을 수 있습니다.
참고로 여기서 말하는 parameter 정보들은 위의 로그에서 "?"에 해당되는 값을 의미합니다.
해당 문제는 dependency를 추가하게 되면 쉽게 해결할 수 있습니다.
build.gradle에 다음과 같이 jpa 실행 로그를 parameter 정보까지 확인하도록 도와주는 의존성 추가를 해주겠습니다.
// build.gradle
dependencies {
// querydsl log
implementation "com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0"
}
의존성을 추가한 뒤 다시 동일한 테스트를 실행해 보겠습니다.
이전과 달리 parameter 정보가 매핑된 query를 명확히 확인하는 로그가 찍히는 것을 볼 수 있습니다.
이상으로 spring boot 3 버전 이후 gradle에 querydsl 사용 환경 설정하는 방법에 대해 간단하게 알아보는 시간이었습니다.
읽어주셔서 감사합니다.