코틀린에서는 interface의 default method 를 지원하지 않는다. interface 에 구현부를 포함한 메소들 포함해서 사용할 순 있지만 java의 default method 와는 다르다.
자바 코드로 변환된 내용을 보면 알겠지만 내부클래스를 정의하고 그 안에 static 메소드로 만들어진다. 이로 인해 코틀린 환경에서 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함할 경우 컴파일 단계에서 아래와 같은 에러를 마주하게 된다.
No property betweenOsVer found for type ${EntityName}
spring-data-jpa 에서는 "쿼리 메소드" 라는 기능이 있는데 JpaRepository 를 상속한 interface 해당하는 구현체를 자동으로 만들어주는 과정에서 그곳에 포함된 추상메소드 이름을 기반으로 쿼리를 만들어주는 기능이다.
이러한 "쿼리 메소드" 기능을 사용하려면 메소드 이름을 find…By, read…By, query…By, count…By 와 같이 사전에 약속된 네이밍을 따라야 한다.
다만 사용자가 직접 쿼리를 정의해야 하는 경우가 있을 수 있기 때문에 default method 는 "쿼리 메소드" 대상에 포함시키지 않도록 되어 있다.
그런데 코틀린에는 default 메소드가 없다보니 정의된 메소드에 대해 모두 "쿼리메소드" 가 수행되게 되고 약속된 네이밍이 아닌 메소드에 대해 위와 같은 에러메시지를 리턴하게 된다.
결국 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함하려면 default 메소드만 가능하다는 말이다. 다르게 말하면 현재 코틀린 환경에서는 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함하면 안된다.
QueryDsl을 사용할 경우 JpaRepository 를 상속한 interface 에 default method를 정의할 일은 없다. @Query 기능을 활용하거나 "쿼리메소드" 기능을 사용할 때나 필요할 것이다.
다만 나의 경우 BooleanExpression 로 동적쿼리를 만드는 과정에서 관련 메소드를 정의하는데 사용하고자 했다. 알다시피 동적쿼리를 만드는 방법에는 BooleanExpression과 BooleanBuilder 가 있는데 둘 중 BooleanExpression 이 선호되기 때문이다.
BooleanExpression 의 경우 조건을 동적으로 만들어주는 메소드가 필요하고 이는 Entity에 종속적이기 때문에 JpaRepository 를 상속한 interface 두는 게 맞다고 생각했기 때문이다.
그런데 위와 같은 이유로 인해 나는 코틀린 환경에서는 BooleanExpression 동적으로 만들어주는 메소드를 Entity 에 companion object 를 활용해서 만들어서 사용 중이다.
https://velog.io/@lsb156/SpringBoot-with-Kotlin에서-JpaRepository-default-method-구현에-따른-오류
'Backend > Kotlin' 카테고리의 다른 글
[Kotlin] 확장함수 언제 어떻게 사용해야 할까? (0) | 2021.12.24 |
---|---|
코틀린 with, apply, also, let, run (0) | 2021.12.23 |
[Kotlin] 제네릭(내가 필요한 것만 정리..) (0) | 2021.12.06 |
[Kotlin] inline (0) | 2021.12.06 |
[Kotlin] 코틀린에서 유틸함수 만들기 (0) | 2021.11.24 |