Kotlin与JPA/Hibernate:没有`open`没有懒加载?

joh*_*hnp 7 orm hibernate jpa lazy-loading kotlin

大多数Kotlin JPA示例代码都是这样的

class Person(val name: String, val age: Int) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

甚至

data class Person(val name: String="", val age: Int=0) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

现在,Hibernate用户指南,以及我认为其他几个ORM,声明他们通常想要创建代理或以其他方式扩展模型类,但是为了允许在Kotlin中必须明确定义类open.数据类目前这是不可能的,从我自己的经验来看,我认为大多数人在Kotlin中编写JPA实体时都没有考虑过.

所以,为了解决我的问题(毕竟这是stackoverflow),这样做是否足够

 open class Person(val name: String, val age: Int) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

或者我们真的要做

 open class Person(open val name: String, open val age: Int) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

不必要地阻碍ORM正常工作?
如果确实有害,我们应该建议向IntelliJ IDEA添加一个警告,如果一个类有一个@Entity注释,它应该被定义open.

vod*_*dan 9

您提供的教程指定:

实体类必须具有公共或受保护的无参构造函数...接口可能不被指定为实体......实体类不能是最终的.实体类的方法或持久性实例变量可能不是最终的.

Kotlin类遵循JavaBeans惯例来设置setter/getter.

如果您的ORM具有上述要求,那么您确实必须open在类及其方法上指定:

open class Person(open val name: String = "", 
                  open val age: Int = 0)
Run Code Online (Sandbox Code Playgroud)

所有构造函数参数的默认值允许Kotlin生成另一个空构造函数.或者,您可以将其作为辅助构造函数提供:

open class Person(open val name: String, open val age: Int) {
    constructor() : this("", 0)
}
Run Code Online (Sandbox Code Playgroud)

请注意,open val创建一个私有final字段和一个open getter.如果这还不够,请使用注释@JvmField open val name.

像你使用的ORM对Kotlin代码有额外的摩擦,因为他们使用了可疑的设计模式(比如让所有东西都不是最终的).

一个好的选择是使用Kotlin特定的ORM.例如,Exposed由JetBrains支持并用于它的一些产品,这些产品本身就说明了一切.另一个选择是Ebean正式支持Kotlin(感谢@johnp)