본문 바로가기

⭐🌏 JPA/🌏 QueryDSL

QueryDSL 설정방법

# 참고 블로그

https://highright96.tistory.com/32

 

[Querydsl] 스프링 부트에 Querydsl 설정하기

build.Gradle에 Querydsl 설정 추가 플러그인 추가 plugins { ... id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" ... } 의존성 추가 dependencies { ... implementation 'com.querydsl:querydsl-jpa'..

highright96.tistory.com

# QueryDSL 설정하기

- JPA, JPQL 쓰다보니 한가지 문제점이 간단한 CRUD는 문제없이 가능하지만 JOIN...하는게 너무 복잡하고 어려웠다.

물론 통계자료 같은 복잡한 쿼리는 네이티브 쿼리로 짜는게 효율적일거 같고, 스칼라 서브쿼리나, 이너조인, 아웃터 조인 하는게 JPQL은 너무 어려움... 그래서 과감히 버리고 QueryDSL을 쓰기로 했다.

 

- 사실 나한테는 네이티브 쿼리로 짜는게 제일 좋다... 근데 네이티브 쿼리로 짜게되면 DB 및 테이블에 종속이 되어 버리니 문제가 되는거 같긴하다. 사실 DB나 테이블을 한번 만들어 놓으면 바꿀일이 거의 없는데... 코드 재사용 및 효율성 측면에서 QueryDSL을 쓰는것 같다.

 

1. build.gradle 설정하기

- //querydsl 추가 라고 주석을 달아놓은 부분만 새롭게 추가해 주면 된다.

//querydsl 추가
buildscript {
    ext {
        queryDslVersion = "5.0.0"
    }
}

plugins {
    id 'org.springframework.boot' version '2.7.2'
    id 'io.spring.dependency-management' version '1.0.12.RELEASE'
    id 'java'

    //querydsl 추가
    id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
}

group = 'com.study'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'org.postgresql:postgresql'
    implementation 'org.springdoc:springdoc-openapi-ui:1.6.10'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    // aop logger
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
    implementation group: 'commons-io', name: 'commons-io', version: '2.11.0'
    implementation group: 'org.json', name: 'json', version: '20200518'

    //querydsl 추가
    implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
    implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
}

tasks.named('test') {
    useJUnitPlatform()
}

//querydsl 추가
def querydslDir = "$buildDir/generated/querydsl"

querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}
sourceSets {
    main.java.srcDir querydslDir
}
compileQuerydsl {
    options.annotationProcessorPath = configurations.querydsl
}
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}

2. App.config 파일 생성 및 작성

- 파일위치: 위치는 메인 클래스랑 동일한 경로에 넣어주면 된다? 나는 그렇게 경로를 설정함

- 파일 내용

- @Bean 이란 뭘까? 간단하게 말하면, 자바의 보통객체가 스프링 컨테이너에 의해서 관리되면 그것은 스프링 Bean이 된다.우리는 IOC 패턴을 쉽게 사용하기 위해서 스프링 프레임워크의 IOC 컨테이너를 제공받아서 사용한다. 그러면 그때 IOC컨테이너에 등록되는 자바객체를 스프링 빈 이라고 부른다. 즉, 메타데이터처럼 이름을 붙여 사용하기 편하게 하는 것이다.

import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;

@Configuration
@RequiredArgsConstructor
public class AppConfig {

    private final EntityManager em;

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

}

3. gradle 컴파일

- 우측 상단에 Gradle 탭을 누르면 아래와 같은 화면이 나타난다.

- compileQuerydsl을 하면 자동적으로 생성이 된다.

4. 컴파일이 완료되면 아래와 같은 폴더가 생성이 된다.

위와 같은 폴더구조와 파일이 생기는 이유는 Entity를 참조하여 QueryDSL에 맞는 Entity파일을 생성한다.

예를들어 Hello라는 Entity 파일을 새로 생성했을 경우 QHello라는 Entity를 자체적으로 생성한다.

- Hello 엔티티의 내용은 아래와 같다.

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
@Getter
@Setter
public class Hello {

    @Id
    @GeneratedValue
    private Long id;
}

- compileQuerydsl을 실행하여 자동으로 생긴 Entity의 모습

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;


/**
 * QHello is a Querydsl query type for Hello
 */
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QHello extends EntityPathBase<Hello> {

    private static final long serialVersionUID = -414768845L;

    public static final QHello hello = new QHello("hello");

    public final NumberPath<Long> id = createNumber("id", Long.class);

    public QHello(String variable) {
        super(Hello.class, forVariable(variable));
    }

    public QHello(Path<? extends Hello> path) {
        super(path.getType(), path.getMetadata());
    }

    public QHello(PathMetadata metadata) {
        super(Hello.class, metadata);
    }

}

5. 기본적인 QueryDSL 설정은 끝났다. 이제 간단한 쿼리를 작성해 보자.

- 아래의 값으로 DB에서 조회를 하면 1개의 값이 나온다.

SELECT {컬럼명} FROM {TABLE} WHERE title = '하이';

- DB 값 결과 → 김승현 이라는 값 하나만 조회해 가져온다.

6. 위의 내용을 QueryDSL로 작성해본다.

- Controller

    /** QueryDSL 하나의 값 자동 셀렉트... */
    @GetMapping("/oneValueAuto")
    public String oneValueAuto() {
        return boardService.oneValueAuto();
    }

- Service

    public String oneValueAuto() {
        QBoardEntity m = QBoardEntity.boardEntity;
        String result = jpaQueryFactory
                .select(m.description)
                .from(m)
                .where(m.title.eq("하이"))
                .fetchOne();
        return result;
    }

- 결과 조회, DB에서 조회한것과 같이 1개의 값만을 가져온것을 확인 할 수 있다.

7. 여러개의 값을 가져오는 쿼리를 작성해보자.

- 쿼리문은 아래와 같다.

select description from board;

- 결과는 아래와 같다.

8. 위의 내용을 QueryDSL로 작성을 해보자.

- Controller

    /** QueryDSL 하나의 값만 조회해오기 */
    @GetMapping("/oneProjectionTest")
    public GeneralResponse<?> oneProjectionTest() {
        return boardService.oneProjectionTest();
    }

- Service

    public GeneralResponse<?> oneProjectionTest() {
        QBoardEntity m = QBoardEntity.boardEntity;
        List<String> result = jpaQueryFactory
                .select(m.description)
                .from(m)
                .fetch();
        return GeneralResponse.builder()
                .status(true)
                .message("QueryDSL 테스트")
                .data(result)
                .build();
    }

- 결과 조회

- 끗 -

'⭐🌏 JPA > 🌏 QueryDSL' 카테고리의 다른 글

QueryDSL [SELECT * FROM TABLE]  (0) 2022.08.26