ihoneymon / blog-comments

honeymon.io 댓글관리
0 stars 0 forks source link

/tech/2020/07/09/gradle-annotation-processor-with-querydsl #9

Open utterances-bot opened 4 years ago

utterances-bot commented 4 years ago

[gradle] 그레이들 Annotation processor 와 Querydsl - I'm honeymon(JiHeon Kim).

새로운 맥북을 받고 스프링 부트 버전업을 하면 그레이들도 버전업을 해야하는 상황이 온다.

http://honeymon.io/tech/2020/07/09/gradle-annotation-processor-with-querydsl.html

ihoneymon commented 4 years ago

정리하자면 다음과 같이 사용하는게 편함

m-fire commented 4 years ago

좋은 포스팅 잘 보았습니다. 다만, 궁금한것이 Spring-boot 버전에 따른 Querydsl 의존성 버전을 자동관리 되게하는 방법은 없을까요?

ihoneymon commented 4 years ago

@m-fire 스프링 부트에서 Querydsl 의존성 버전은 관리합니다. 다만, Querydsl 을 사용하기 위해서 필요한 컴파일 사전작업에 대해서는 관여하지 않았습니다. 여기에 가장 큰 영향을 끼치는 것이 그레이들 버전입니다. 그레이들 버전에 따라서 애노테이션 프로세서 작동방식이 상이합니다. 그레이들은 꾸준하게 빠른 버전 업그레이드를 진행하고 있습니다. 스프링 부트는 그에 맞춰 스프링 부트 플러그인을 제공하고 있습니다.

Querydsl은 스프링 부트 개발팀에서 관리하는 라이브러리가 아니라는 점과 최근 들어서 플러그인이나 라이브러리 업데이트가 빈번하지 않다는 것에 관심을 가지셨으면 합니다. 오픈소스는 누군가 이용할 수 있지만, 그 컨트리뷰터가 항상 최신업데이트를 제공하지 않는다는 것을 유의해주셨으면 합니다.

최신 업데이트에 맞춰서 대응해줬으면 하지만, 내가 그렇듯 컨트리뷰터가 항상 대응해줄 수 없습니다. 그러니, 상황상황에 맞춰서 적절한 해법을 찾고, 가능하다면 다른 이들과 공유할 수 있기를 바랄 뿐입니다. 그런 작은 바람을 스스로 실천한 포스팅이었습니다.

Juyeon-Lee commented 3 years ago

헉 진짜 Q객체 안 떠서 구글링하다가 덕분에 해결됐네요 감사합니다!!!! :)

oen142 commented 3 years ago

헉 지금까지 플러그인을 사용해서 했었는데 버전업데이트 하다가 먹통이 되어서 고민을 많이 한점인데, 너무 꿀같은 포스팅 감사합니다!

zieunx commented 3 years ago

와 너무 유익합니다... 좋은 포스팅 감사드립니다!

blackcctv commented 3 years ago

이 글을 보고 해결했습니다. 감사합니다.

jeon9825 commented 3 years ago

이 글 보고 해결했어요ㅠㅠ 계속 빌드 오류가 나서 이것저것 참고했는데 이 게시물이 제일 깔끔하게 정리된 것 같아요!!

chans08 commented 3 years ago

질문있습니다~ Q클래스가 build/generated/sources/annotationProcessor 에 생겼는데, 코드 상에서 Q 클래스를 can not resolved 해버리네요. intellij에서 Project Structure > Project Settings > Modules에 generated 폴더에 팬돌아간거 같은 마크가 찍힌게 생겼는데 정작 그 폴더 안에 들어가보면 Q 클래스가 안보여요. 제가 인텔리제이랑 querydsl에 초초보입니다. 어떻게 해결할 수 있을까요??

chans08 commented 3 years ago

일단 intellij 소스 파일 세팅에서 해당 annotationProcessor 폴더를 추가해줘서 import 해오긴 했는데 자연스럽게 가져오는 방법이 있을까요??

chans08 commented 3 years ago

위 방법은 gradle 새로 build해버리면 물거품처럼 사라지네요.. ㅜㅜ 어떻게 해결해야 할까요?

ihoneymon commented 3 years ago

@chans08 님이 사용하고 계시는 인텔리제이 버전이 몇인지 사용하고 있는 그레이들 버전이 어떻게 되는지 부터 알려주시면 조금 더 빠르게 해결방법을 찾아볼 수 있을 듯 합니다.

괜찮다면 build.gradle 스크립트 파일을 공유해주셔도 좋구요. 공개가 어렵다면 이메일(ihoneymon@gmail.com) 으로 보내주시면 살펴볼게요.

굳이 생성되는 build/generated/sources/annotationProcessor 를 수동으로 추가하거나 할 필요는 없습니다. 프로젝트 설정에서 'Enable annotation processing' 체크를 하면 그레이들 설정을 확인하고 그에 적절한 위치에서 파일을 불러옵니다.

chans08 commented 3 years ago

안녕하세요 허니몬님. 현재 해당 문제는 한번 QClass를 복붙해주니까 다음번부터는 자동 생성이 잘 되어 해결된 상태이며, 다른 문제가 발생하여 질문메일 드려요~ 일단 인텔리제이버전은 2020.3이고, 그레이들은 v6.7.1 입니다.

제가 허니몬님 블로그(https://adrenal.tistory.com/25)를 참고하여 querydsl을 사용하여 동적 쿼리를 생성하여 잘 사용하였는데 간간이

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property search found for type TxRequest! at org.springframework.data.mapping.PropertyPath.(PropertyPath.java:90) Caused by: org.springframework.data.mapping.PropertyReferenceException: No property search found for type TxRequest!

at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:437) at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:413) at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:366) at java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:324) at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:348) at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:331) at org.springframework.data.repository.query.parser.Part.(Part.java:81) at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:249) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:250) at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:383) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:384) at org.springframework.data.repository.query.parser.PartTree.(PartTree.java:92) at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.(PartTreeJpaQuery.java:89)

이런 에러가 뜨더니 이제는 계속 에러가 뜨면서 작동이 안됩니다. ㅜㅜ

제 프로젝트는 [image: image.png] public interface TxRequestRepositoryCustom { Page search(SearchTxInfo searchTxInfo, Pageable pageable); }

@Slf4j public class TxRequestRepositoryImpl extends QuerydslRepositorySupport implements TxRequestRepositoryCustom {

/**

이런식으로 구현이 되어있는데 자꾸 search 메소드를 쿼리분석해서 만들어내려는것 같습니다.

이런 경우 어떻게 해결할 수 있을까요??

허니몬님의 답변을 간절히 기다립니다. 감사합니다.

2021년 2월 25일 (목) 오후 11:30, Kim Ji-Heon notifications@github.com님이 작성:

@chans08 https://github.com/chans08 님이 사용하고 계시는 인텔리제이 버전이 몇인지 사용하고 있는 그레이들 버전이 어떻게 되는지 부터 알려주시면 조금 더 빠르게 해결방법을 찾아볼 수 있을 듯 합니다.

괜찮다면 build.gradle 스크립트 파일을 공유해주셔도 좋구요. 공개가 어렵다면 이메일(ihoneymon@gmail.com) 으로 보내주시면 살펴볼게요.

굳이 생성되는 build/generated/sources/annotationProcessor 를 수동으로 추가하거나 할 필요는 없습니다. 프로젝트 설정에서 'Enable annotation processing' 체크를 하면 그레이들 설정을 확인하고 그에 적절한 위치에서 파일을 불러옵니다.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ihoneymon/blog-comments/issues/9#issuecomment-785936102, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALN6GXA2BSSW4GLUWDQZASTTAZNJDANCNFSM4O73WOMA .

ihoneymon commented 3 years ago

@chans08 님이 보여준 코드를 따라서 구현했을 때, 저는 별다른 특이사항은 없는데... 제가 작성한 예제와 비교 한번 해보시겠어요?

https://github.com/ihoneymon/20210226-querydsl-sample/tree/main/src/main/java/com/example/demo/repository

그래도 안되면... @_@);; 행아웃으로 프로젝트 한번 설명해주시면 살펴보는 방법도 있긴 합니다.

chans08 commented 3 years ago

아, 답변 감사합니다. 원인은 알았어요! repository랑 repositoryCustom, repsitoryCustomImpl 이렇게 다른 패키지에 넣어놨는데 한곳에 몰아넣고 그안에 impl 패키지를 만들어놓으니까 문제가 사라지더라구요..

대체 왜 됐다 안됐다하다가 뻑났는지는, 좀더 살펴봐야할것 같아요.

친절하고 빠른답변 감사드립니다! 좋은하루되세요~

2021년 2월 26일 (금) 오후 8:34, Kim Ji-Heon notifications@github.com님이 작성:

@chans08 https://github.com/chans08 님이 보여준 코드를 따라서 구현했을 때, 저는 별다른 특이사항은 없는데... 제가 작성한 예제와 비교 한번 해보시겠어요?

https://github.com/ihoneymon/20210226-querydsl-sample/tree/main/src/main/java/com/example/demo/repository

  • java: 11
  • gradle: 6.8.2
  • Spring Boot 2.4.3
  • Intellij 2020.3 입니다.

그래도 안되면... @_@);; 행아웃으로 프로젝트 한번 설명해주시면 살펴보는 방법도 있긴 합니다.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ihoneymon/blog-comments/issues/9#issuecomment-786593072, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALN6GXAJ5JSIV4RH3A4VMQ3TA6BM7ANCNFSM4O73WOMA .

ihoneymon commented 3 years ago

@chans08 됐다안됐다 하는건, Querydsl 과 관련된 부분에 문제가 발생하기 때문이겠죠. 제가 공유드린 예제처럼 사용한다면 별다른 문제는 생기지 않을 겁니다.

문제 해결하고 안정적으로 개발 진행하시면 좋겠습니다. ^^

JPWon-1 commented 3 years ago

mapstruct와 같이 사용할때 javaCompile 에러가 생기는데 혹시 위의 설정에서 바뀐 부분이 있을까요?

ihoneymon commented 3 years ago

@JPWon-1 님, mapStruct 의존성 선언에 대해서도 annotationProcessor 선언이 필요할 수 있습니다.

JPWon-1 commented 3 years ago

네에...본 포스팅과는 다른 질문이지만... mapstruct 와 querydsl의 생성 폴더를 다르게 할 수있나요? mapstruct 는 dto가 있는 폴더에 impl 을 만들고 싶고 querydsl은 지정한 폴더에다가 만들고 싶어서요

JPWon-1 commented 3 years ago

javaCompile 할 때 같은 위치에 두니 gradle clean 하면서 같이 삭제되는 문제도 있는데 혹시 해결 방법 아실까요?

ihoneymon commented 3 years ago

@JPWon-1

코드를 통해 생성되는 생성물을 소스코드 내에 포함시키게 효율적인지 잘 모르겠습니다. 그레이들 빌드 과정에서 생성되는 생성물이라 clean을 실행하면 삭제되는 게 당연한거고, 빌드를 수행해서 생성하면 되니까요.

그래도 필요하다면, JavaCompile 태스크를 확장한 사용자정의 태스크를 이용하여 원하는 위치에 지정할 수 있을 겁니다.

/** QClass 생성 */
task generateQueryDSL(type: JavaCompile, group: 'build') {
    doFirst {
        delete queryDslOutput
        queryDslOutput.mkdirs()
    }
    source = sourceSets.main.java
    classpath = configurations.compile
    destinationDir = queryDslOutput
    options.compilerArgs = [
            '-proc:only',
            '-processor',
            'com.querydsl.apt.jpa.JPAAnnotationProcessor' // 여기에 각 라이브러리에서 제공하는 annotation processor 를 선언해야함
    ]
}
compileJava.dependsOn(generateQueryDSL)

개인적으로, annotationProcessor 수행으로 생긴 생성물은 버전관리대상에서 제외하는 것을 선호합니다.

JPWon-1 commented 3 years ago

그렇군요!!!너무나도 감사합니다. 많이 배워갑니다!!

chlwlgml4321 commented 2 years ago

안녕하세요 @ihoneymon 님 Qclass 못 찾아오는 문제가 있었는데 덕분에 해결하였습니다 감사합니다 !!! :) 근데 다른 문제가 발생하여서 이곳저곳 다 찾아보다가 허니몬님께 여쭤봅니다..

제 설정에 문제가 있는건지 새로운 entity를 생성해서 컴파일하면 그 해당 Qclass 는 생성이 안되어서 개발이 어려운 상황입니다.. 어떻게 해결해야할까요.. ㅠㅠ 허니몬님 답변 간절히 기다리겠습니다...!

ihoneymon commented 2 years ago

@chlwlgml4321 님, 답이 늦었습니다.

새롭게 생성된 Entity 클래스가 annotationProcessor 작업경로에 없어서 그럴 수도 있고, 엔티티 클래스가 생성되었을 때, 컴파일러가 자동으로 수행되지 않아서 그럴수도 있습니다.

안되는 이유는 말씀하신 것만으로는 확인하기 어렵습니다. 빌드스크립트와 사용하시는 개발환경을 함께 봐야합니다.

괜찮으시다면, 이메일로 문의주시면 좀 더 빠르게 답변드릴 수 있을 것 같습니다.

anymobi commented 1 year ago

안녕하세요. 포스팅 해주신 내용 덕분에 querydsl 문제없이 사용중입니다. 제가 지금 멀티모듈로 프로젝트를 진행중인데 Project A

설정방법에 대해서 혹시 해보시거나 하신 적이 있으실까요?

ihoneymon commented 1 year ago

@anymobi 님께서 이야기하시는 구성을 잠시 생각해보면... Module A와 Module B 에서 공통으로 사용하는 Entity 는 보통 Module-core(or Module-Domain) 으로 공통적인 엔티티를 모아서 Module A와 Module B에서 각각 사용합니다.

Module-core 모듈에 대해서 Querydsl 처리한 Entity 라면 굳이 Module A와 Module B에서 추가적으로 Querydsl 처리를 할 필요가 없습니다. Module A와 Module B에만 존재하는 엔티티가 있다면 @EntityScan@EntityRepositoryScan 으로 Module A와 Module B Entity가 있는 패키지를 각각 컴포넌트 해야 합니다. 거기다가 Querydsl 의존성도 각각 추가로 선언해주셔야 합니다.

Module-core 를 참조할 때 컴파일된 클래스(애노테이션을 읽고 처리된 Q클래스 포함)를 참조하니까 Module A와 Module B에서는 Module-core에 대해서는 별도로 annotationProcessor 를 선언하지 않아도 됩니다.

정리해보자면, 'Module-core, Module A과 Module B 각각 Querydsl 처리를 한다.' 입니다.

ihoneymon commented 1 year ago

Spring Boot 3.0(이상) + JPA(Jakarta Persistence 3.X) + Querydsl 5.X 은 다음과 같이 설정합니다.

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