๊ด€๋ฆฌ ๋ฉ”๋‰ด

DOing

Querydsl์ด๋ž€? ๋ณธ๋ฌธ

JPA

Querydsl์ด๋ž€?

mangdo 2021. 8. 4. 15:05

๐ŸŒฑ Querydsl?

์ฟผ๋ฆฌ๋ฅผ ์ž๋ฐ”์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๊ธฐ์ˆ ์ด๋‹ค.

Spring Data JPA๋กœ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ณต์žกํ•œ ์ฟผ๋ฆฌ/๋™์  ์ฟผ๋ฆฌ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ž๋ฐ”์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ๋ฒ•์˜ค๋ฅ˜๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์— ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

๐ŸŒฑ build.gradle์—์„œ Querydsl ์„ค์ •

plugins {
    id 'org.springframework.boot' version '2.5.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    //querydsl ์ถ”๊ฐ€
    id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
    id 'java'
}

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

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    //querydsl ์ถ”๊ฐ€
    implementation 'com.querydsl:querydsl-jpa'

    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

//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
}

 

๊ฒฐ๊ณผ์ ์œผ๋กœ Querydsl๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” JPQL์ด ๋œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

์‹คํ–‰๋˜๋Š” JPQL์„ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด application.properties์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•œ๋‹ค.

spring.jpa.properties.hibernate.use_sql_comments: true

 

 


 

๐ŸŒฑ Querydsl์—์„œ ์ž๋™ ์ƒ์„ฑํ•ด์ค€ QEntity

 Querydsl์ด ์ง์ ‘ ๋งŒ๋“  hello๋ผ๋Š” Entity๋ฅผ ๋ณด๊ณ  QEntity๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

 ์ฃผ์˜ํ•  ์ ์€ generated๋œ QํŒŒ์ผ๋“ค์€ git์—๋‹ค๊ฐ€ ์˜ฌ๋ฆฌ๋ฉด ์•ˆ๋œ๋‹ค๋Š” ์ ์ด๋‹ค.

 ์™œ๋ƒํ•˜๋ฉด ์ƒ์„ฑ๋œ QํŒŒ์ผ๋“ค์€ ์‹œ์Šคํ…œ์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „์ด ์˜ฌ๋ผ๊ฐ€๊ฒŒ๋˜๋ฉด ์ƒ์„ฑ๋œ ์„ธ๋ถ€ ๋‚ด์šฉ๋“ค์ด ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์–ด์„œ ์ด๋Ÿฐ ๊ฒƒ๋“ค์ด git์— ์˜ฌ๋ผ๊ฐ€๋ฉด ์•ˆ๋œ๋‹ค. ์ด๋Ÿฐ ํŒŒ์ผ๋“ค์„ gitignore๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์• ์ดˆ์— ํŒŒ์ผ ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ๋กœ๋ฅผ build๋กœ ํ•ด์ฃผ๋ฉด ํŽธํ•˜๋‹ค. ๋ณดํ†ต buildํด๋”๋Š” ๊ธฐ๋ณธ์œผ๋กœ gitignore์„ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

๐ŸŒฑ QHello.java

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

    private static final long serialVersionUID = -1579446036L;

    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);
    }

}

 

 

๐ŸŒฑ JPQL vs Querydsl ๋น„๊ต

์ฟผ๋ฆฌ๋ฅผ ์ž๋ฐ”์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•๋ถ„์— ๋ฌธ๋ฒ•์˜ค๋ฅ˜๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์— ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

import static com.example.inflearnquerydsl.entity.QMember.member;

@SpringBootTest
@Transactional
public class QuerydslBasicTest {

    @PersistenceContext
    EntityManager em;

    JPAQueryFactory queryFactory; // ๋™์‹œ์„ฑ ๋ฌธ์ œ?
    // ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ๊ฐ™์€ EntityManager์— ์ ‘๊ทผํ•ด๋„, 
    // ํŠธ๋žœ์žญ์…˜ ๋งˆ๋‹ค ๋ณ„๋„์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋™์‹œ์„ฑ ๋ฌธ์ œ๋Š” ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    @BeforeEach
    public void before() {
        queryFactory = new JPAQueryFactory(em);

        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        em.persist(teamA);
        em.persist(teamB);

        Member member1 = new Member("member1", 10, teamA);
        Member member2 = new Member("member2", 20, teamA);
        Member member3 = new Member("member3", 30, teamB);
        Member member4 = new Member("member4", 40, teamB);
        em.persist(member1);
        em.persist(member2);
        em.persist(member3);
        em.persist(member4);
    }

    @Test
    public void startJPQL() {
        //member1์„ ์ฐพ์•„๋ผ.
        String qlString =
                "select m from Member m " +
                        "where m.username = :username";

        Member findMember = em.createQuery(qlString, Member.class)
                .setParameter("username", "member1")
                .getSingleResult();

        assertThat(findMember.getUsername()).isEqualTo("member1");
    }


    @Test
    public void startQuerydsl() {
        //member1์„ ์ฐพ์•„๋ผ.
        Member findMember = queryFactory
                .select(member)
                .from(member)
                .where(member.username.eq("member1"))//ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ์ฒ˜๋ฆฌ
                .fetchOne();

        assertThat(findMember.getUsername()).isEqualTo("member1");
    }
}