带有 JPA 的 Kotlin:默认构造函数地狱 [英] Kotlin with JPA: default constructor hell

查看:36
本文介绍了带有 JPA 的 Kotlin:默认构造函数地狱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 JPA 的要求,@Entity 类应该有一个默认(非参数)构造函数来在从数据库中检索对象时实例化对象.

在 Kotlin 中,在主构造函数中声明属性非常方便,如下例所示:

class Person(val name: String, val age: Int) {/* ... */}

但是当非 arg 构造函数被声明为辅助构造函数时,它需要传递主构造函数的值,因此它们需要一些有效值,例如:

@Entityclass Person(val name: String, val age: Int) {私有构造函数(): this("", 0)}

如果属性有一些比 StringInt 更复杂的类型并且它们不可为空,那么为它们提供值看起来很糟糕,尤其是当主构造函数和 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆