line / kotlin-jdsl

Kotlin library that makes it easy to build and execute queries without generated metamodel
https://kotlin-jdsl.gitbook.io/docs/
Apache License 2.0
651 stars 85 forks source link

No property 'findSlice' found for type 에러 질문 #725

Closed mingyu-lee closed 1 week ago

mingyu-lee commented 2 weeks ago

안녕하세요

kotlin jdsl spring support 사용 중입니다

다음과 같은 코드를 작성했는데

MeetRepository

interface MeetRepository : JpaRepository<Meet, Long>, KotlinJdslJpqlExecutor

MeetReader

@Repository
class MeetReader(
    private val meetRepository: MeetRepository
) {

    fun findAllMeets(query: MeetFindAllQuery, pageable: Pageable): Slice<MeetFindAllInfo?> {
        return meetRepository.findSlice(pageable) {
            selectNew<MeetFindAllInfo>(
                path(Meet::id),
                path(Meet::name),
                path(Meet::userId),
                path(Profile::nickname),
                path(Image::staticUrl),
                path(Place::id),
                path(Place::name),
                path(Place::latitude),
                path(Place::longitude),
                path(Meet::type),
                path(Meet::money),
                path(Meet::status),
                path(Meet::startTime),
                path(Meet::endTime),
                path(Meet::createdAt),
                path(Meet::likeCount),
                caseWhen(
                    path(MeetLike::id).isNull(),
                ).then(
                    Expressions.booleanLiteral(false)
                )
            ).from(
                entity(Meet::class),
                join(Place::class).on(path(Meet::placeId).eq(path(Place::id))),
                join(Profile::class).on(path(Meet::userId).eq(path(Profile::userId))),
                join(ProfileImage::class).on(path(ProfileImage::profile).eq(entity(Profile::class))),
                join(Image::class).on(path(ProfileImage::image).eq(entity(Image::class))),
                leftJoin(Meet::likes).on(path(MeetLike::userId).eq(query.requestUserId))
            ).where(
                path(Meet::startTime).greaterThanOrEqualTo(
                    query.searchStartDate.atStartOfDay().toInstant(ZoneOffset.UTC)
                )
                    .and(
                        path(Meet::endTime).lessThanOrEqualTo(
                            query.searchEndDate.atTime(LocalTime.MAX).toInstant(ZoneOffset.UTC)
                        )
                    ),
            ).orderBy(
                path(Meet::createdAt).desc()
            )
        }
    }
}

애플리케이션 실행시 이런 에러가 나오네요

Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract org.springframework.data.domain.Slice com.linecorp.kotlinjdsl.support.spring.data.jpa.repository.KotlinJdslJpqlExecutor.findSlice(org.springframework.data.domain.Pageable,kotlin.jvm.functions.Function1); Reason: Failed to create query for method public abstract org.springframework.data.domain.Slice com.linecorp.kotlinjdsl.support.spring.data.jpa.repository.KotlinJdslJpqlExecutor.findSlice(org.springframework.data.domain.Pageable,kotlin.jvm.functions.Function1)! No property 'findSlice' found for type 'Meet'; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract org.springframework.data.domain.Slice com.linecorp.kotlinjdsl.support.spring.data.jpa.repository.KotlinJdslJpqlExecutor.findSlice(org.springframework.data.domain.Pageable,kotlin.jvm.functions.Function1)! No property 'findSlice' found for type 'Meet'
    at org.springframework.data.repository.query.QueryCreationException.create(QueryCreationException.java:101)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:107)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$mapMethodsToQuery$1(QueryExecutorMethodInterceptor.java:95)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1061)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:97)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:87)
    at java.base/java.util.Optional.map(Optional.java:260)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:87)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:365)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:323)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:231)
    at org.springframework.data.util.Lazy.get(Lazy.java:115)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:329)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
    ... 58 common frames omitted
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract org.springframework.data.domain.Slice com.linecorp.kotlinjdsl.support.spring.data.jpa.repository.KotlinJdslJpqlExecutor.findSlice(org.springframework.data.domain.Pageable,kotlin.jvm.functions.Function1)! No property 'findSlice' found for type 'Meet'
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:96)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:119)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:259)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:93)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:103)
    ... 80 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'findSlice' found for type 'Meet'
    at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:91)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:438)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:414)
    at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:367)
    at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:349)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:332)
    at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81)
    at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:250)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:251)
    at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:384)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:385)
    at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:93)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:89)
    ... 84 common frames omitted

혹시 어떤 부분이 문제인지 확인 해주실 수 있나요~?

감사합니다

mingyu-lee commented 2 weeks ago

참고로 gradle multi module 구조이고요 meet 모듈에서 jpa 모듈을 참고ㅎkrh, kotlin jdsl은 jpa 모듈에 선언되어있어요

kotlin jdsl 버전은 3.4.2 spring 버전은 2.7.18 kotlin은 1.9.24 입니다 java 17 입니다

meet - build.gradle.kts


dependencies {
    // infrastructure
    implementation(project(":infrastructure:jpa"))
}

jpa - build.gradle.kts

val kotlinJDSLVersion: String by project
val mysqlConnectorVersion: String by project

plugins {
    id("org.jetbrains.kotlin.plugin.jpa")
}

dependencies {
    api("org.springframework.boot:spring-boot-starter-data-jpa")
    api("org.hibernate:hibernate-core:5.4.27.Final")
    api("com.mysql:mysql-connector-j:$mysqlConnectorVersion")

    api("com.linecorp.kotlin-jdsl:jpql-dsl:$kotlinJDSLVersion")
    api("com.linecorp.kotlin-jdsl:jpql-render:$kotlinJDSLVersion")
    api("com.linecorp.kotlin-jdsl:spring-data-jpa-support:$kotlinJDSLVersion")

    implementation("org.flywaydb:flyway-core")
    implementation("org.flywaydb:flyway-mysql")
}
shouwn commented 2 weeks ago

안녕하세요. 혹시 spring을 debug 모드로 켜서 KotlinJdslAutoConfiguration 설정이 enable 되었는지 확인해주실 수 있으신가요?

말씀주신 에러는 KotlinJdslJpaRepositoryFactoryBeanPostProcessor를 통한 custom implementation 주입이 되지 않았을 때 발생하는 에러로, DataJpaTest를 사용하실 때에 Import로 KotlinJdslAutoConfiguration를 포함하지 않았거나, 자체 Spring AutoConfigure를 작성하시면서 KotlinJdslAutoConfiguration가 제외되지 않았을까 생각됩니다.

cj848 commented 2 weeks ago

전체 설정이 확인이 안된 상황에서 혼란스러울수 있는 답변을 드린것 같아 답글은 삭제 했습니다. 위 @shouwn 님 답변 확인해봐주시고 안되시면 재현 가능한 최소한의 프로젝트를 공개해주시면 확인 해볼 수 있을것 같습니다.

mingyu-lee commented 2 weeks ago

@shouwn @cj848 답변 감사합니다. 급한대로 querydsl 사용해서 진행 중입니다. 시간이 된다면 다시 한번 설정 해볼게요 ㅜㅜ

shouwn commented 1 week ago

@mingyu-lee 넵 해결이 된다면 좋겠네요. ㅠㅠ

추가로 Spring Boot 3.x를 쓰고 계신데도 불구하고 jakarta EntityManager가 클래스패스에 없는 경우도 있는 것 같습니다. 동일 문제일 수 있어 당시 이야기 나누었던 디스코드 쓰레드의 링크를 남깁니다.

https://discord.com/channels/1087271586832318494/1124136741650042931/1250684882582241320

위에 말씀드린 내용과 디스코드 쓰레드를 통해서도 해결이 되지 않으면 다시 이슈를 오픈해주세요.