====== Gradle에서 JPA 2 MetaModel 생성 ======
[[https://github.com/hibernate/hibernate-metamodelgen|Hibernate MetamodelGen]]을 이용하여 JPA2 MetaModel을 생성하는 예를 보여준다.
실제로는 compile 태스크에 들어가는게 좋으나, 현재 지원을 안 해서, 독릭적으로 JavaCompile 태스크를 만들고, 거기서 Annotation Processor만 호출하도록 변경한 것이다.
* ''-proc:only'' 옵션 때문에 실제 컴파일을 하지 않는다.
* **Java 6** 이상에서만 작동한다.
* TODO [[http://netframework.tistory.com/462|Programming is Fun :: Gradle 5.0에서의 querydsl Q-class 생성]]
===== QueryDSL =====
* [[http://honeymon.io/tech/2020/07/09/gradle-annotation-processor-with-querydsl.html|[gradle] 그레이들 Annotation processor 와 Querydsl]]
* [[java:querydsl|QueryDSL]]의 경우 [[https://github.com/ewerk/gradle-plugins/tree/master/querydsl-plugin|Graldle QueryDSL Plugin]]으로 해결 가능하다. : [[:intellij_idea|IntelliJ IDEA]] 연동에 문제 일으킴. ''annotationProcessor'' 더 권장.
apply plugin: "com.ewerk.gradle.plugins.querydsl"
compile "com.querydsl:querydsl-jpa:$queryDslVersion"
ext {
querydslSrcDir = 'src/main/generated'
}
querydsl {
library = "com.querydsl:querydsl-apt"
jpa = true
querydslSourcesDir = querydslSrcDir
}
sourceSets {
main {
java {
srcDirs += file(querydslSrcDir)
}
}
}
idea {
module {
generatedSourceDirs += file(querydslSrcDir)
}
}
* ''compileQueryDsl'' task로 코드 생성을 할 수 있다.
gradlew clean cleanQuerydslSourcesDir compileQueryDsl
혹은
gradlew cleanQuerydslSourcesDir initQuerydslSourcesDir compileQuerydsl processQUerydslResources
# cleanQuerydslSourcesDir 를 하지 않을 경우 기존 생성된 코드 때문에 오류가 발생함.
===== Cannot find symbol 오류 =====
* [[java:querydsl|QueryDSL]]과 Hibernate/Eclipse Metamodel Generator를 함께 사용할 때 아직 생성되지 않은 메타 모델 클래스를 사용하는 코드들 때문에 ''cannot find symbol'' 에러가 발생할 수 있는데, 이는 이 둘을 서로 따로 생성했을 때 발생하는 현상이다.
* 정황상 [[java:lombok|Lombok]]을 함께 사용할 경우 각 AP가 실행된 뒤에 다시 lombok AP가 돌면서 발생하는 것으로 보인다.
* 이 둘을 함께 지정해서 APT 를 수행해야 에러가 나지 않는다.
"-processor",
"com.mysema.query.apt.jpa.JPAAnnotationProcessor,org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor"
===== Gradle Annotation Process 예 =====
http://alvinalexander.com/java/jwarehouse/hibernate/build.gradle.shtml 에 있는 것을 옮겼다.
Gradle 기반으로 정적 분석 도구 사용시에 여기서 자동 생성된 클래스는 정적 분석에서 예외처리해줘야 한다.(''/Q[A-Z].*\.class/'', ''/.*\_.class/'') [[java:static_analysis|Java Static Analysis]] 를 참조한다.
ext.jpaMetamodelGeneratedDir = "$buildDir/생성된 메타 모델 클래스를 저장할 디렉토리"
configurations {
jpaMetamodelGen {
extendsFrom compile
}
}
dependencies {
jpaMetamodelGen "org.hibernate:hibernate-jpamodelgen:1.2.0.Final"
}
sourceSets {
main {
java {
srcDir jpaMetamodelGeneratedDir
}
}
}
idea {
module {
sourceDirs += file(jpaMetamodelGeneratedDir)
}
}
task generateJpaMetamodel(type: JavaCompile) {
def targetDir = file(jpaMetamodelGeneratedDir)
def compiledDestinationDir = "${buildDir}/tmp/apt-jpa"
doFirst {
// 항상 대상 디렉토리를 먼저 비우고 시작해야 한다.
delete(targetDir)
targetDir.mkdirs()
}
doLast {
delete(compiledDestinationDir) // UP-TO-DATE 방지
}
// -proc:only 는 Annotation Processor로 소스 생성만 한다 컴파일은 하지 않음
// -s 경로 는 생성된 소스가 들어갈 디렉토리를 뜻한다.
classpath = configurations.jpaMetamodelGen
source = sourceSets.main.java
destinationDir = file(compiledDestinationDir)
options.define(
compilerArgs: [
"-nowarn",
"-proc:only",
"-encoding", "UTF-8",
"-s", targetDir.absolutePath,
// processor 지정은 안해도 된다. 안하면 모든 어노테이션 프로세서 실행
"-processor", "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor" ]
)
}
// 필요하면 compileJava가 generateJpaMetamodel 에 의존하도록 변경한다.
==== Lombok 사용시 ====
[[java:lombok|Lombok]] 사용시 문제가 된다면 [[https://medium.com/@geminikim/%EA%B0%9C%EC%9D%B8%EC%B7%A8%ED%96%A5-jpa-%EC%82%AC%EC%9A%A9%EA%B8%B0-querydsl-gradle-lombok-76c509aec60e|개인취향 JPA 사용기 - QueryDSL + Gradle + Lombok – Gemini Kim – Medium]] 참고. [[https://github.com/ewerk/gradle-plugins/issues/59|querydsl + lombok problem · Issue #59 · ewerk/gradle-plugins]]
task generateQueryDSL(type: JavaCompile, group: 'build') {
source = sourceSets.main.java
classpath = configurations.compile
destinationDir = queryDslOutput
options.compilerArgs = [
"-proc:only",
/********************* 핵심 포인트! *********************/
"-processor", 'com.querydsl.apt.jpa.JPAAnnotationProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
]
}
compileJava.dependsOn(generateQueryDSL)