๐Ÿ“˜ Web/Spring, JPA

[JPA] SpringBoot(2.x version)์— QueryDsl JPA ์ ์šฉ (gradle ์„ค์ •)

a n u e 2023. 7. 18. 11:28

 

QueryDsl์€ SQL, JPQL ๋“ฑ์„ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” builder opensource framework ์ด๋‹ค.

 : ์‚ฌ๋žŒ์ด Query๋ฅผ ์งœ๋‹ค๋ณด๋ฉด ๋ณดํ†ต ์ˆ˜์ž‘์—…์œผ๋กœ ํ•˜๊ธฐ์— ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธธ ์—ฌ์ง€๊ฐ€ ์žˆ๋Š”๋ฐ (String์ด๋‹ค ๋ณด๋‹ˆ)

์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. 

 

QueryDsl์€ Query ์ƒ์„ฑ์„ ์ž๋™ํ™” ํ•˜์—ฌ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋ฏ€๋กœ, ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ์— ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๊ณ 

๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋‚˜ ๋™์  ์ฟผ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ์— ์žˆ์–ด ํ•œ๊ณ„๊ฐ€ ์žˆ๋Š” ์ˆœ์ˆ˜ JPA๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋„ ์‚ฌ์šฉํ•œ๋‹ค.

 

์•„์ง ์‹ค๋ฌด์—์„œ ์“ฐ๊ณ ์žˆ์ง€๋Š” ์•Š์œผ๋‚˜, ์‹ค๋ฌด์— ๋งŽ์ด ์ ์šฉํ•œ๋‹ค๊ณ  ํ•ด์„œ ์–•๊ฒŒ๋‚˜๋งˆ ํŒŒ๋ณด์•˜๋‹ค.

 


 

1.  build.gradle ์…‹ํŒ…

dependencies {
	...
    //querydsl
    implementation 'com.querydsl:querydsl-jpa'
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}


//querydsl option

// querydsl QClass ํŒŒ์ผ ์ƒ์„ฑ ์œ„์น˜๋ฅผ ์ง€์ •
// def generated = "$buildDir/generated/querydsl"
def generated = 'src/main/generated'

tasks.withType(JavaCompile) {
    options.getGeneratedSourceOutputDirectory().set(file(generated))
}

// java source set Qclass ์œ„์น˜ ์ถ”๊ฐ€
sourceSets {
    main.java.srcDirs += [ generated ]
}

// gradle clean ์‹œ, QClass ๋””๋ ‰ํ† ๋ฆฌ ์‚ญ์ œ
clean {
    delete file(generated)
}

 

  : gradle ์„ค์ • ํ›„, gradle clean > gradle build > gradle compileJava ์ˆœ์œผ๋กœ ์‹คํ–‰

 ๊ทธ๋Ÿผ generated ์— ์ •์˜ํ•œ ์œ„์น˜์— ์ƒˆ๋กœ์šด ๋””๋ ‰ํ† ๋ฆฌ์™€ ํ•จ๊ป˜ Qclass ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ๋‹ค.

 

Qclass๋Š” Entity๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ์„ฑ๋˜๋ฉฐ

JPAAnnotationProcessor๊ฐ€ ์ปดํŒŒ์ผ ์‹œ์ ์— @Entity ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ฐพ์•„ ๋ถ„์„ํ•ด ๋งŒ๋“ ๋‹ค.

(์—”ํ‹ฐํ‹ฐ์™€ ๋™์ผํ•œ ํŒŒ์ผ ๋ช… ์•ž์— Q๊ฐ€ ๋ถ™์–ด์žˆ๋‹ค.)

QueryDsl์€ ์ฟผ๋ฆฌ ์ž‘์„ฑ ์‹œ, ์ด๋Ÿฌํ•œ Qclass๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Query๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 

 


2.  Config ์„ค์ •

@Configuration
public class QueryDslConfig {
	@PersistenceContext
    private EntityManager entityManager;
    @Bean
    public JPAQueryFactory jpaQueryFactory() { return new JPAQueryFactory(entityManager); }
}

  : JPAQueryFactory๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•ด ํ”„๋กœ์ ํŠธ ์ „์—ญ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

 

โ— JPAQueryFactory ๊ฐ์ฒด๊ฐ€ import ๋˜์ง€ ์•Š์•„์„œ ๊ณ ์ƒ์„ ๋งŽ์ด ํ–ˆ๋Š”๋ฐ intellij ์บ์‹œ ์‚ญ์ œ ํ•˜๋‹ˆ๊นŒ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ๋๋‹ค ;;;;

๋‚ด์‹œ๊ฐ„ ๋Œ๋ ค์ค˜์š” ;;; ๋™์ผ ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ,  File > invalidate Caches ๋ฅผ ๋ˆŒ๋Ÿฌ ์บ์‹œ ์‚ญ์ œํ•˜๊ธฐ

 

 


 

3.  .gitignore ์„ค์ • (๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ $buildDir/generated/querydsl์ธ ๊ฒฝ์šฐ ํŒจ์Šค)

  :  build.gradle ํŒŒ์ผ์—์„œ "$buildDir/generated/querydsl" ๋กœ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ง€์ •ํ•ด์ฃผ์—ˆ์œผ๋ฉด ์ƒ๊ด€์—†์œผ๋‚˜

 (build ๋ฃจํŠธ๋Š” ์• ์ดˆ์— .gitignore์— ์„ค์ •๋˜์–ด ์žˆ์Œ)

๋‚˜์˜ ๊ฒฝ์šฐ์—๋Š” build ๋ฃจํŠธ๋กœ ๋งŒ๋“ค๋ฉด Qclass๊ฐ€ ์ œ๋Œ€๋กœ import๋˜์ง€ ์•Š์•„์„œ, src ์•„๋ž˜์— ํด๋”๋ฅผ ๋งŒ๋“ค๋„๋ก ํ–ˆ๋‹ค.

 

.gitignore์— ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฒ„์ „๊ด€๋ฆฌ๊ฐ€ ๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

/src/main/generated/

 


 

๊ทธ๋Ÿผ ์ด์ œ ๊ธฐ๋ณธ์ ์ธ ์…‹ํŒ…์€ ๋๋‚ฌ์œผ๋‹ˆ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์ž !

 

 SELECT * FROM TEST WHERE FIELD_1 IN ('ํ…Œ์ŠคํŠธ1', 'ํ…Œ์ŠคํŠธ2');


0. Entity

@Entity
@Getter
@Setter
@Table(name = "testTable")
public class Test {
	@Id
	@column(name = "field_1")
    private String field1;
}

 

 1. Controller์— ํ…Œ์ŠคํŠธ์šฉ ์กฐํšŒ API ์ถ”๊ฐ€

@PostMapping("/Test")
public ResponseEntity select(@RequestBody String[] arr) {
	return new ResponseEntity(service.select(arr), HttpStatus.OK);
}

 

 

2. Service

public List<Test> select(String[] arr) {
	List<Test> rslt = testRepo.findByField1(arr);
	return rslt;
}

 

 

3. Repository

@Repository
public interface TestRepo extends JpaRepository<Test>, TestRepoCustom {
}

 

 

4. RepositoryCustom

public interface TestRepoCustom {
	List<Test> findByField1(String[] arr);
}

 

5. RepositoryImpl

@RequiredArgsConstructor
public class TestRepoImpl implements TestRepoCustom {
	private final JPAQueryFactory jpaQueryFactory;
    
    @Override
    public List<Test> findByField1(String[] arr) {
    	return jpaQueryFactory
        .selectFrom(test)
        .where(test.field1.in(arr))
        .fetch();
    }
}