Kotlin与JPA / Hibernate:没有“开放”没有懒加载?
大多数Kotlin JPA示例代码看起来像这样
class Person(val name: String, val age: Int) { /* ... */ }
甚至
data class Person(val name: String="", val age: Int=0) { /* ... */ }
现在, Hibernate用户指南和其他几个ORM都表示,他们通常要创建代理或扩展模型类,但是为了允许在Kotlin中将类明确定义为open
。 这对于数据类来说目前是不可能的,从我自己的经验来看,大多数人在Kotlin编写JPA实体时并没有考虑这个问题。
所以,来我的问题(毕竟这是stackoverflow),是否足够
open class Person(val name: String, val age: Int) { /* ... */ }
或者我们真的不得不这样做
open class Person(open val name: String, open val age: Int) { /* ... */ }
不是不必要地妨碍ORM正确地完成工作?
如果确实是有害的,我们应该建议给IntelliJ IDEA添加一个警告,如果一个类有一个@Entity
注解,它应该被定义为open
。
您提供的教程指定:
实体类必须有一个公共或保护的无参数构造函数…接口不能被指定为实体…实体类不能是最终的。 没有实体类的方法或持久化实例变量可能是最终的。
Kotlin类遵循JavaBeans约定为setter / getters。
如果您的ORM具有上述要求,那么您确实必须在类和它的方法上指定open
:
open class Person(open val name: String = "", open val age: Int = 0)
所有构造函数参数的默认值都允许Kotlin生成一个额外的空构造函数。 或者,您可以将其作为辅助构造函数提供:
open class Person(open val name: String, open val age: Int) { constructor() : this("", 0) }
请注意, open val
会创建一个私人的最终字段和一个开放的getter。 如果这还不够,请使用@JvmField open val name
注释。
由于使用了可疑的设计模式(比如使所有的东西都不是最终的),所以你使用的ORM与Kotlin代码有更多的摩擦。
一个好的选择是使用Kotlin特定的ORM。 例如, Exposed由JetBrains支持,并用于其一些产品,这本身就是一个例子。 另一个选择是正式支持Kotlin的Ebean(感谢@ johnp)