+ 00 00 0000

Have any Questions?

07_Simple Coding – Backend – Querydsl – 기본 요약

07_Simple Coding – Backend – Querydsl – 기본 요약

📃 요약

실무에서는 MVC 디자인 패턴 속해서 스프링부트를 사용해 코딩을 진행함. 파일관리 시 파일을 용도에 맞게 정리하듯이 MVC 디자인 패턴도 패키지 및 클래스를 용도에 맞게 분류해서 코딩을 진행함

요소 기술 :

– Basic : java & spring boot

📃 기술 구현

스펙 :

- intellij
- java
- spring boot

📃 Querydsl :

- DB 에 접속하여 CRUD를 실행하는 라이브러리
- sql 문을 작성하는 것이 아니라 sql 문의 키워드에 해당하는 함수를 메소드 체이닝을 이용해서 작성하는 방식
- 다이나믹 쿼리 작성해야 할때 Querydsl 를 많이 사용함
- 원본 클래스를 사용하지 않고, 복사본(Q클래스) 을 사용해서 실행함
- 때에 따라서 JPA 기본 함수외에 직접 sql 문을 작성해야 할때가 있음.
이때  JPQL 를 사용하지 않고 Querydsl 로 대체해서 사용하는 회사도 있음(배달의 민족 등)

build.gradle

plugins {
    id 'java'
    id 'war'
    id 'org.springframework.boot' version '2.7.11'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'

    // TODO: 1) querydsl 추가
    id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

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

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    ...

    // TODO: 2) querydsl 추가
    implementation "com.querydsl:querydsl-jpa:5.0.0"
    annotationProcessor "com.querydsl:querydsl-apt:5.0.0"

    ...
}

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

// TODO: 3) querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"

querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}

sourceSets {
    main.java.srcDir querydslDir
}

configurations {
    querydsl.extendsFrom compileClasspath
}

compileQuerydsl {
    options.annotationProcessorPath = configurations.querydsl
}

QuerydslConfig.java

- config 폴더를 만들어서 추가함
- Querydsl 과 JPA 를 연결하는 설정 파일
    1) JPAQueryFactory 객체에 JPA 객체를 넣어서 연동시킴
    2) Querydsl 사용시 다른 자바 파일에서 JPAQueryFactory 객체를 생성하면 사용할 수 있음
package com.example.jpaquerydslexam.config;

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

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Configuration
public class QuerydslConfig {
    @PersistenceContext
    private EntityManager entityManager;

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

querydsl 클래스 : 조회

- 사용할 함수를 미리 정의해 놓은 클래스
- 여기서 직접 SQL 문을 작성할 수 있음 : 체이닝 함수를 연결해 쿼리문 작성함
- 예 :
    1) select -> select() 함수 
    2) from -> from() 함수
    3) where -> where() 함수
    4) order by -> orderBy() 함수
    ...
- JPAQueryFactory @Audowired 로 DI 함
- 엔티티 복사본 Q 클래스를 생성해서 사용함
사용법 : 
@Repository
public class 클래스명 {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private Q클래스명 객체명 = Q클래스명.객체명;    // 복사본  Q 클래스

    public List<엔티티명> 함수명(변수명) {

        List<엔티티명> list = queryFactory
                .selectFrom(객체명)
                .where(
                        객체명.속성명.contains(매개변수명)
                )
                .fetch(); // 조회 실행

        return list;
    }
    ...
}

예 :
@Repository
public class 클래스명 {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private QDept dept = QDept.dept;    // 복사본  Q 클래스

    //    1) dname 으로 like 검색
    public List<Dept> querydslByDname(String dname) {

        List<Dept> list = queryFactory
                .selectFrom(dept)
                .where(
                        dept.dname.contains(dname)
                )
                .fetch(); // 조회 실행

        return list;
    }
}

querydsl 클래스 : 페이징 처리

- 사용할 함수를 미리 정의해 놓은 클래스
- 여기서 직접 SQL 문을 작성할 수 있음 : 체이닝 함수를 연결해 쿼리문 작성함
- 예 :
    1) select -> select() 함수 
    2) from -> from() 함수
    3) where -> where() 함수
    4) order by -> orderBy() 함수
    ...
- JPAQueryFactory @Audowired 로 DI 함
- 엔티티 복사본 Q 클래스를 생성해서 사용함
- PageImpl<>(결과객체, pageable, 전체카운트) : 객체를 이용해 페이징처리함

querydsl 클래스 / 함수

사용법 : 
@Repository
public class 클래스명 {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private Q클래스명 객체명 = Q클래스명.객체명;    // 복사본  Q 클래스

    public List<엔티티명> 함수명(변수명) {

        List<엔티티명> list = queryFactory
                .selectFrom(객체명)
                .where(
                        객체명.속성명.contains(매개변수명)
                )
                .fetch(); // 조회 실행

        Long count = queryFactory
                .select(객체명.count())
                .from(객체명)
                .where(
                        객체명.속성명.contains(매개변수명)
                )
                .fetch(); // 조회 실행

        // PageImpl<>(결과객체, pageable, 전체카운트)
        return new PageImpl<>(list, pageable, count);
    }
    ...
}

예 :
@Repository
public class 클래스명 {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private QDept dept = QDept.dept;    // 복사본  Q 클래스

    //    1) dname 으로 like 검색
    public Page<Dept> querydslByDname(String dname) {

        List<Dept> list = queryFactory
                .selectFrom(dept)
                .where(
                        dept.dname.contains(dname)
                )
                .fetch(); // 조회 실행

        Long count = queryFactory
                .select(dept.count())
                .from(dept)
                .where(
                        dept.dname.contains(dname)
                )
                .fetchOne(); // 조회 실행

        // PageImpl<>(결과객체, pageable, 전체카운트)
        return new PageImpl<>(list, pageable, count);
    }
}

querydsl 클래스 : 다이나믹 쿼리

- 다이나믹 쿼리 : 조건의 형태가 매개변수의 값에 따라 달라지는 것
- JPQL 에서는 사용하기 어려우나 querydsl 은 간단하게 사용할 수 있게 지원함

querydsl 클래스 / 함수

사용법 : 
@Repository
public class 클래스명 {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private Q클래스명 객체명 = Q클래스명.객체명;    // 복사본  Q 클래스

    //    동적 쿼리 : ename or job
    public List<객체명> 함수명(String 변수명, String 변수명2) {

        BooleanBuilder builder = new BooleanBuilder();

        if (변수명 != null) {
            builder.and(객체명.속성명.contains(변수명));
        }

        if (변수명2 != null) {
            builder.and(객체명.속성명.contains(변수명));
        }

        return queryFactory
                .selectFrom(객체명)
                .where(builder) // 위에서 만든 동적으로 만들어 지는 where 절 추가
                .fetch(); // 조회 실행
    }
    ...
}

예 :
@Repository
public class DeptRepositoryDsl {

    @Autowired
    private JPAQueryFactory queryFactory; // querydsl DI

    private QEmp emp = QEmp.emp;    // 복사본  Q 클래스

    public List<Dept> querydslByDynamicName(String dname, String loc) {

        BooleanBuilder builder = new BooleanBuilder();

//    dname 이 null 이 아니면 where dname like '%dname%' 추가
        if (dname != null) {
            builder.and(dept.dname.contains(dname));
        }

//    loc 이 null 이 아니면 where loc like '%loc%' 추가
        if (loc != null) {
            builder.and(dept.loc.contains(loc));
        }

        return queryFactory
                .selectFrom(dept)
                .where(builder) // 위에서 만든 동적으로 만들어 지는 where 절 추가
                .fetch();       // 조회 실행
    }
}

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다