JPA/Hibernate 的 Kotlin:没有 `open` 就没有延迟加载?
Kotlin with JPA/Hibernate: no lazy-loading without `open`?
大多数 Kotlin JPA 示例代码如下所示
class Person(val name: String, val age: Int) { /* ... */ }
甚至
data class Person(val name: String="", val age: Int=0) { /* ... */ }
现在,Hibernate User Guide,我认为还有其他几个 ORM,声明他们通常想要创建代理或以其他方式扩展模型 class,但为了在 Kotlin 中允许 class 必须明确定义 open
。这对于数据 classes 目前是不可能的,我认为,根据我自己的经验,大多数人在使用 Kotlin 编写 JPA 实体时不会考虑它。
那么,来回答我的问题(毕竟这是 Whosebug),是否足够
open class Person(val name: String, val age: Int) { /* ... */ }
或者我们真的必须做
open class Person(open val name: String, open val age: Int) { /* ... */ }
不要不必要地阻碍 ORM 正常工作?
如果它真的有害,我们可能应该建议在 IntelliJ IDEA 中添加一个警告,如果 class 有一个 @Entity
注释,它应该被定义为 open
.
您提供的教程说明:
The entity class must have a public or protected no-argument constructor ... Interface may not be designated as an entity ... The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
Kotlin class遵循 setters/getters 的 JavaBeans 约定。
如果您的 ORM 有上述要求,那么您确实需要在 class 及其方法上指定 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 is supported by JetBrains and used for some of its products, which speaks for itself. Another option is Ebean 正式支持 Kotlin(感谢@johnp)
kotlin allopen 编译器插件在这里可能值得一提。
<pluginOptions>
...
<option>all-open:annotation=javax.persistence.Entity</option>
</pluginOptions>
这将使所有 类 注释 @Entity
打开。
大多数 Kotlin JPA 示例代码如下所示
class Person(val name: String, val age: Int) { /* ... */ }
甚至
data class Person(val name: String="", val age: Int=0) { /* ... */ }
现在,Hibernate User Guide,我认为还有其他几个 ORM,声明他们通常想要创建代理或以其他方式扩展模型 class,但为了在 Kotlin 中允许 class 必须明确定义 open
。这对于数据 classes 目前是不可能的,我认为,根据我自己的经验,大多数人在使用 Kotlin 编写 JPA 实体时不会考虑它。
那么,来回答我的问题(毕竟这是 Whosebug),是否足够
open class Person(val name: String, val age: Int) { /* ... */ }
或者我们真的必须做
open class Person(open val name: String, open val age: Int) { /* ... */ }
不要不必要地阻碍 ORM 正常工作?
如果它真的有害,我们可能应该建议在 IntelliJ IDEA 中添加一个警告,如果 class 有一个 @Entity
注释,它应该被定义为 open
.
您提供的教程说明:
The entity class must have a public or protected no-argument constructor ... Interface may not be designated as an entity ... The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
Kotlin class遵循 setters/getters 的 JavaBeans 约定。
如果您的 ORM 有上述要求,那么您确实需要在 class 及其方法上指定 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 is supported by JetBrains and used for some of its products, which speaks for itself. Another option is Ebean 正式支持 Kotlin(感谢@johnp)
kotlin allopen 编译器插件在这里可能值得一提。
<pluginOptions>
...
<option>all-open:annotation=javax.persistence.Entity</option>
</pluginOptions>
这将使所有 类 注释 @Entity
打开。