带有 JPA 的 Kotlin:默认构造函数地狱 [英] Kotlin with JPA: default constructor hell
问题描述
根据 JPA 的要求,@Entity
类应该有一个默认(非参数)构造函数来在从数据库中检索对象时实例化对象.
在 Kotlin 中,在主构造函数中声明属性非常方便,如下例所示:
class Person(val name: String, val age: Int) {/* ... */}
但是当非 arg 构造函数被声明为辅助构造函数时,它需要传递主构造函数的值,因此它们需要一些有效值,例如:
@Entityclass Person(val name: String, val age: Int) {私有构造函数(): this("", 0)}
如果属性有一些比 String
和 Int
更复杂的类型并且它们不可为空,那么为它们提供值看起来很糟糕,尤其是当主构造函数和 init
块中有很多代码并且参数被主动使用时——当它们要通过反射重新分配时,大部分代码将再次执行.>
而且,val
-properties 在构造函数执行后不能重新赋值,因此也失去了不变性.
那么问题是:Kotlin 代码如何在不重复代码、选择神奇"初始值和失去不变性的情况下适应 JPA 的工作?
附言除了 JPA,Hibernate 是否可以构造没有默认构造函数的对象?
自 Kotlin 1.0.6 起,kotlin-noarg
编译器插件为类生成合成默认构造函数已使用选定注释进行注释.
如果你使用 gradle,应用 kotlin-jpa
插件就足以为用 @Entity
注释的类生成默认构造函数:
buildscript {依赖{类路径org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"}}应用插件:kotlin-jpa"
对于 Maven:
<artifactId>kotlin-maven-plugin</artifactId><groupId>org.jetbrains.kotlin</groupId><version>${kotlin.version}</version><配置><编译器插件><plugin>jpa</plugin></compilerPlugins></配置><依赖项><依赖><groupId>org.jetbrains.kotlin</groupId><artifactId>kotlin-maven-noarg</artifactId><version>${kotlin.version}</version></依赖></依赖项></插件>
As JPA requires, @Entity
classes should have a default (non-arg) constructor to instantiate the objects when retrieving them from the database.
In Kotlin, properties are very convenient to declare within the primary constructor, as in the following example:
class Person(val name: String, val age: Int) { /* ... */ }
But when the non-arg constructor is declared as a secondary one it requires values for the primary constructor to be passed, so some valid values are needed for them, like here:
@Entity
class Person(val name: String, val age: Int) {
private constructor(): this("", 0)
}
In case when the properties have some more complex type than just String
and Int
and they're non-nullable, it looks totally bad to provide the values for them, especially when there's much code in primary constructor and init
blocks and when the parameters are actively used -- when they're to be reassigned through reflection most of the code is going to be executed again.
Moreover, val
-properties cannot be reassigned after the constructor executes, so immutability is also lost.
So the question is: how can Kotlin code be adapted to work with JPA without code duplication, choosing "magic" initial values and loss of immutability?
P.S. Is it true that Hibernate aside of JPA can construct objects with no default constructor?
As of Kotlin 1.0.6, the kotlin-noarg
compiler plugin generates synthetic default construtors for classes that have been annotated with selected annotations.
If you use gradle, applying the kotlin-jpa
plugin is enough to generate default constructors for classes annotated with @Entity
:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
}
}
apply plugin: "kotlin-jpa"
For Maven:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<plugin>jpa</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
这篇关于带有 JPA 的 Kotlin:默认构造函数地狱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!