Spring๐Ÿƒ

SpringData ์ฟผ๋ฆฌ์™€ QueryDSL

wannaDevelopIt 2023. 2. 8. 15:22

1. SpringData ์ฟผ๋ฆฌ

SpringData Common์˜ CrudRepository์™€ PagingAndSortingRepository ์ฟผ๋ฆฌ๊ธฐ๋Šฅ์„ ์ œ๊ณต

 

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ ‘๋‘์–ด Find, Get, Query, Count, ...
๋„์ž…๋ถ€ Distinct, First(N), Top(N)
ํ”„๋กœํผํ‹ฐ ํ‘œํ˜„์‹ Person.Address.ZipCode => find(Person)ByAddress_ZipCode(...)
์กฐ๊ฑด์‹ IgnoreCase, Between, LessThan, GreaterThan, Like, Contains, ...
์ •๋ ฌ ์กฐ๊ฑด OrderBy{ํ”„๋กœํผํ‹ฐ}Asc
๋ฆฌํ„ด ํƒ€์ž… E, Optional<E>, List<E>, Page<E>, Slice<E>, Stream<E>
๋งค๊ฐœ๋ณ€์ˆ˜ Pageable, Sort

2. QueryDSL

QueryDSL์˜ Predicate ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์กฐ๊ฑด๋ฌธ์„ ์—ฌ๋Ÿฌ ๊ฐœ ๊ตฌ์„ฑํ•˜์—ฌ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค

~ ์ฃผ๋กœ findOne(Predicate), findAll(Predicate) ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

- findOne(Predicate) : Optional<T> ๋ฆฌํ„ด

- findAll : List<T> | Page<T> | Iterable<T> | Slice<T> ๋ฆฌํ„ด

 

Type Safe ๊ธฐ๋Šฅ

์กฐ๊ฑด๋ฌธ ๊ตฌ์„ฑ ์‹œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด, ํ•„๋“œ ์กฐ๊ฑด์ด ์‹ค์ œ ํƒ€์ž…๊ณผ ์ผ์น˜ํ•˜๋Š” ์ง€ ์ฒดํฌํ•ด์ค€๋‹ค

 

์žฅ์ 

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

2. ์ž๋™ ์™„์„ฑ ๋“ฑ IDE์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค

3. ๋™์ ์ธ ์ฟผ๋ฆฌ ์ž‘์„ฑ์ด ํŽธ๋ฆฌํ•˜๋‹ค

4. ์ฟผ๋ฆฌ ์ž‘์„ฑ ์‹œ ์ œ์•ฝ ์กฐ๊ฑด ๋“ฑ์„ ๋ฉ”์„œ๋“œ ์ถ”์ถœ์„ ํ†ตํ•ด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์›๋ฆฌ

QueryDSL ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด SpringData์— ์˜ํ•ด QueryDslPreficateExecutor ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค

-> QueryDslPreficateExecutor ์ธํ„ฐํŽ˜์ด์Šค : Repository๊ฐ€ QueryDSL์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค

 

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

~ Spring 2.x : queryDSL ์˜์กด์„ฑ, ์†Œ์Šค ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •, annotation ํ”„๋กœ์„ธ์„œ ์„ค์ •, Task ์ •์˜๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค

plugins {
    ...
    id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}

configurations {
    ...
    querydsl.extendsFrom compileClasspath
}

def querydslSrcDir = 'src/querydsl/generated'

querydsl {
    library = "com.querydsl:querydsl-apt"
    jpa = true
    querydslSourcesDir = querydslSrcDir
}

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', querydslSrcDir]
        }
    }
}

project.afterEvaluate {
    project.tasks.compileQuerydsl.options.compilerArgs = [
            "-proc:only",
            "-processor", project.querydsl.processors() +
                    ',lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
    ]
}

dependencies {
    implementation("com.querydsl:querydsl-jpa") // querydsl
    implementation("com.querydsl:querydsl-apt") // querydsl
    ...
}

gradle ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ ์›๋ฆฌ

  • Gradle ๋นŒ๋“œ์‹œ์— QueryDSL์€ ํ”„๋กœ์ ํŠธ ๋‚ด์˜ **@Entity** ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•œ ํด๋ž˜์Šค๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ ,  **JPAAnnotationProcessor**๋ฅผ ์‚ฌ์šฉํ•ด Qํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • **querydsl-apt**๊ฐ€ **@Entity** ๋ฐ **@Id** ๋“ฑ์˜ ๋งคํ•‘์ •๋ณด Annotation์„ ์•Œ ์ˆ˜ ์žˆ๋„๋ก, **javax.persistence**๊ณผ **javax.annotation**์„ annotationProcessor์— ํ•จ๊ป˜ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • **annotationProcessor**๋Š” Java ์ปดํŒŒ์ผ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ์„œ, ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ„์„ ๋ฐ ์ฒ˜๋ฆฌํ•จ์œผ๋กœ์จ ์ถ”๊ฐ€์ ์ธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ƒ์„ฑ๋œ Qํด๋ž˜์Šค๋ฅผ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก /build/generated ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํ”„๋กœ์ ํŠธ์˜ sourceSet์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋กœ์จ, IDE ์—์„œ๋„ ์ƒ์„ฑ๋œ Qํด๋ž˜์Šค ํŒŒ์ผ์„ ์ธ์‹ํ•˜์—ฌ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Spring 3.x ~ : ์˜์กด์„ฑ ์ถ”๊ฐ€ Only

// application.yml

dependencies {
		....

		// 9. QueryDSL ์ ์šฉ์„ ์œ„ํ•œ ์˜์กด์„ฑ (SpringBoot3.0 ๋ถ€ํ„ฐ๋Š” jakarta ์‚ฌ์šฉํ•ด์•ผํ•จ)
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

Join์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค

  • ์ „์ฒด ์ฑ„๋„์—์„œ ๋‚ด๊ฐ€ ๋ฉ˜์…˜๋œ ์“ฐ๋ ˆ๋“œ ๋ชฉ๋ก ์กฐํšŒ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ
    1. Mention ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ
    2. User - Mention - Thread ๋‹ค๋Œ€๋‹ค ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •
    3. User, Mention ์กฐ๊ฑด์œผ๋กœ Thread ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ์ˆ˜ํ–‰

~ QueryPredicatieExecutor๋กœ๋Š” Join ์—ฐ์‚ฐ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ ๊ตฌํ˜„ ๋ถˆ๊ฐ€๋Šฅ : ๋ฉค๋ฒ„ ์ปฌ๋ ‰์…˜๊นŒ์ง€๋งŒ ์กฐํšŒ ๊ฐ€๋Šฅํ•˜๋‹ค

QuerydslPredicateExecutor์˜ ๋‹จ์  : ๋ฌต์‹œ์  ์กฐ์ธ( 1 Depth ์ž๋™ ์กฐ์ธ) ~ Channel์˜ Thread๊นŒ์ง€๋งŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค

<-> Join ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋˜๋Š” ๋ช…์‹œ์  ์กฐ์ธ(2 Depth ์ด์ƒ ์กฐ์ธ)

Join ์ด ์—†๋Š” ๋Œ€์‹  ์กฐ๊ฑด์ด ๋งŽ์€ ์ฟผ๋ฆฌ

ํ•ด๋‹น ์ฑ„๋„์—์„œ ๋ฉ”์„ธ์ง€๊ฐ€ ์žˆ๋Š” ์“ฐ๋ ˆ๋“œ ๋ชฉ๋ก ์กฐํšŒ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ ~

Channel ์กฐ๊ฑด์œผ๋กœ ๋ฉ”์„ธ์ง€ ๋ณธ๋ฌธ์ด ์žˆ๋Š” Thread ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ์ˆ˜ํ–‰

 

Join ์—†์ด ์กฐ๊ฑด์ด ๋งŽ์ด ์ถ”๊ฐ€๋ ์ˆ˜๋ก **QuerydslPredicateExecutor** ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

~ ์‚ฌ์‹ค ํ˜„์—…์—์„œ๋Š” ์š”๊ฑด ์ž˜ ์•ˆ์“ฐ๊ณ  JPAQueryFactory ๋ฅผ ์ฃผ๋กœ ์“ด๋‹ค