Back-end

[Gradle] Spring boot 3.0.0 이상 Querydsl build.gradle + 멀티 모듈 프로젝트

서채리 2023. 2. 27. 09:28
IntelliJ IDEA
Java 17
Spring Boot 3.x
Groovy
java.lang.NoClassDefFoundError:javax/persistence/Entity
attempt to recreate a file for type qclass
could not find class file for querydsl
Unable to load class 'javax.persistence.Entity'.

위 오류들 해결

 

🌲 멀티 모듈 X

1. build.gradle에 Querydsl 의존성 추가

dependencies {
    ...

    // querydsl
    implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
    annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"    
    //java.lang.NoClassDefFoundError 대응
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api:3.1.0"

    ...

}

 

2. Querydsl Q class 설정

dependencies {
	...
}

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

// ### QueryDSL 관련 설정 시작 ###
// Querydsl Q Class 생성 위치
def querydslDir = '$buildDir/generated/querydsl'

// java source set 에 Querydsl Q Class 위치 추가
sourceSets {
	main.java.srcDirs += [ querydslDir ]
}

// 생성된 Q Class가 컴파일될 디렉토리 설정
tasks.withType(JavaCompile) {
	options.getGeneratedSourceOutputDirectory().set(file(querydslDir))
}

// gradle clean 시, Q Class가 위치한 디렉토리 삭제
clean {
	delete file(querydslDir)
}
// ### QueryDSL 관련 설정 끝 ###

 

3. JPAQueryFactory Bean 등록

@Configuration
public class QuerydslConfig {

    @PersistenceContext
    private EntityManager entityManager;

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

 

4. .gitignore 추가

$buildDir/generated/querydsl

generated는 자동생성되는 파일의 디렉토리이기 때문에 .gitignore에 추가해 준다.

 

 


🌲 멀티 모듈 O

프로젝트 구조

  • admin
    • build.gradle
  • api
    • build.gradle
  • core
    • build.gradle
  • build.gradle

core module에는 entity, repository, util 등 공통적인 내용이 담겨있다.

 

build.gradle (공통)

buildscript {
    ext {
        springBootVersion = '3.0.1'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
        classpath "io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE"
    }
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group = 'com.chaewsstore'
    version = '0.0.1-SNAPSHOT'

    sourceCompatibility = '17'
    compileJava.options.encoding = 'UTF-8'

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        compileOnly 'org.projectlombok:lombok'

        annotationProcessor 'org.projectlombok:lombok'
        annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'

        // querydsl 의존성 추가
        implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
        annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
        annotationProcessor "jakarta.annotation:jakarta.annotation-api"
        annotationProcessor "jakarta.persistence:jakarta.persistence-api:3.1.0"
    }

    test {
        useJUnitPlatform()
    }
}

project(':admin') {
    dependencies {
        implementation project(':core')
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
}

project(':app') {
    dependencies {
        implementation project(':core')
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
}

project(':core') {
    bootJar.enabled = false
    jar.enabled = true
}

 

📌 dependencies에 queryDSL 의존성을 추가해 주었다.

implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api:3.1.0"

 

build.gradle (core)

dependencies {
    ...
}

// ### QueryDSL 관련 설정 시작 ###
// Querydsl Q Class 생성 위치
def querydslDir = '$buildDir/generated/querydsl'

// java source set 에 Querydsl Q Class 위치 추가
sourceSets {
    main.java.srcDirs += [ querydslDir ]
}

// 생성된 Q Class가 컴파일될 디렉토리 설정
tasks.withType(JavaCompile).configureEach {
    options.getGeneratedSourceOutputDirectory().set(file(querydslDir))
}

// gradle clean 시, Q Class가 위치한 디렉토리 삭제
clean.doLast {
    file(querydslDir).deleteDir()
}
// ### QueryDSL 관련 설정 끝 ###

 

📌 core의 build.gradle에 QClass 관련 설정을 해주었다.

def querydslDir = '$buildDir/generated/querydsl'

sourceSets {
    main.java.srcDirs += [ querydslDir ]
}

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

clean.doLast {
    file(querydslDir).deleteDir()
}

 

JPAQueryFactory Bean 등록

 

@Configuration
public class QuerydslConfig {

    @PersistenceContext
    private EntityManager entityManager;

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

 

4. .gitignore 추가

$buildDir/generated/querydsl

Attempt to recreate a file for type

QueryDSL에서 Q Object를 생성할 때 이미 생성되어 있는 경우 발생한다.

따라서 기존 생성되어 있던 Q Object를 삭제하고 다시 실행해야 한다.

 

 

1) IntellliJ 우측 Gradle 탭에서 build > clean 수행

2) Q Object(객체)가 생성되는 폴더 삭제(못 찾겠으면 shift 연속으로 누른 후 Q(Entity이름) 검색해서 위치 찾은 후 폴더 삭제)