考虑以下存储库接口声明:
interface KotlinUserRepository : Repository<User, String> {
fun findById(username: String): User
fun search(username: String) = findById(username)
}
我声明了一个默认的接口方法search(…)
,它默认调用findById(…)
。
启动我的应用程序失败:org.springframework.data.mapping.PropertyReferenceException: No property Search found for type User!
如何使用Spring Data repository接口的Kotlin默认方法并防止PropertyReferenceException
?
5条答案
按热度按时间iyzzxitl1#
TL;DR
Kotlin1.1/1.2首先将默认方法编译为抽象接口方法。无法在Spring Data存储库接口中使用Kotlin的默认方法。
说明
Kotlin允许使用Java运行时版本1.6的默认接口方法。JVM级别的默认接口方法在Java 1.8中引入。这导致Kotlin使用与Java不同的方法来编译默认接口方法。
来自
KotlinUserRepository
的代码编译为:方法
search(…)
编译为抽象接口方法。实现位编译为类DefaultImpls
,它反映了默认的方法签名。一个想要实现KotlinUserRepository
的类需要实现search(…)
。在纯Kotlin环境中使用接口将让Kotlin编译器创建实现位。Spring Data repositories使用下面的代理。仓库中的每个方法必须是:
1.由特定于存储的存储库实现。
1.由自定义实现实现。
1.使用查询注解进行注解。
1.调整方法命名方案以允许查询派生。
在本例中,
search(…)
没有根据您如何实现Java接口而由任何自定义代码实现。Spring Data尝试派生查询并将search(…)
视为User
域类的属性。测试失败并抛出PropertyReferenceException
。这是已知的限制。
参考资料
hts6caw32#
正如Ben所指出的,你现在可以(Kotlin1.2.40+)使用
@JvmDefault
。您需要在build.gradle中启用该选项,如下所示:
我刚刚在Kotlin1.2.41上测试了它,它工作正常。
h43kikqp3#
FWIW Kotlin extension methods在这里很好地为我工作,1 .kt文件:
rkue9o1l4#
最近发布的Kotlin1.2.40现在支持一个实验性功能,通过
@JvmDefault
注解和设置功能标志,可以将Kotlin默认方法编译为Java 8默认方法:Xenable-jvm-default
https://blog.jetbrains.com/kotlin/2018/04/kotlin-1-2-40-is-out/#more-5922
我还没有尝试过,但你的例子理论上应该是这样的:
bweufnob5#
@JvmDefault
现在已弃用。工作正常:和
你需要jvm的选项
-Xjvm-default=all
和注解@JvmDefaultWithCompatibility
以上的接口。