1. ホーム
  2. hibernate

[解決済み] KotlinとJPA:デフォルトのコンストラクタ地獄

2022-04-26 14:12:25

質問

JPAが要求するように。 @Entity クラスは、データベースからオブジェクトを取得する際にインスタンス化するためのデフォルトの (引数以外の) コンストラクタを持つ必要があります。

Kotlinでは、以下の例のように、一次コンストラクタ内でプロパティを宣言すると非常に便利です。

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

しかし、arg 以外のコンストラクタを 2 次コンストラクタとして宣言すると、1 次コンストラクタの値を渡す必要があるため、ここのようにいくつかの有効な値が必要になるのです。

@Entity
class Person(val name: String, val age: Int) {
    private constructor(): this("", 0)
}

プロパティが、単に StringInt 特に、プライマリコンストラクタや init ブロックがあり、パラメータが積極的に使われるとき、つまりリフレクションによってパラメータが再割り当てされるとき、コードのほとんどが再び実行されることになるのです。

さらに val -プロパティはコンストラクタの実行後に再割り当てできないので、不変性も失われます。

つまり、KotlinのコードをJPAに適用する場合、コードの重複や初期値の選択、不変性の喪失を回避するにはどうすればよいでしょうか。

追伸:JPAの脇のHibernateは、デフォルトコンストラクタを持たないオブジェクトを構築できるというのは本当でしょうか?

どのように解決するのですか?

Kotlin 1.0.6時点 は、その kotlin-noarg コンパイラプラグインは、選択されたアノテーションでアノテーションされたクラスに対して合成デフォルトコンストラクタを生成します。

gradleを使用している場合は kotlin-jpa でアノテーションされたクラスのデフォルトコンストラクタを生成するには、プラグインだけで十分です。 @Entity :

buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
    }
}

apply plugin: "kotlin-jpa"

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>