sql >> データベース >  >> RDS >> Mysql

JPAで親/子を挿入すると、MySQLIntegrityConstraintViolationExceptionが発生します

    あなたの関係は双方向である必要はありません。ここのコメントにはいくつかの誤った情報があります。

    また、JPAが値を設定できるように親フィールドについて「知る」必要があると想定したため、フィールド「parentId」を子エンティティに追加したとのことです。問題は、あなたが提供した注釈に基づいて、JPAがフィールドについて知らないということではありません。問題は、フィールドに関する「多すぎる」情報を提供したが、その情報は内部的に一貫していないことです。

    親のフィールドと注釈を次のように変更します:

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "parent_id")
    private List<Child> children;
    

    次に、子エンティティから「parentId」を完全に削除します。以前にJoinTableアノテーションを指定しました。ただし、必要なのはJoinTableではありません。 JoinTableは、2つのエンティティを相互に関連付けるために、追加の3番目のテーブルを作成します。必要なのはJoinColumnだけです。 OneToManyでアノテーションが付けられているフィールドにJoinColumnアノテーションを追加すると、JPA実装は、FKをCHILDテーブルに追加していることを認識します。問題は、JPAに列parent_idですでに定義されているCHILDテーブルがあることです。

    CHILDテーブルの関数とparent_id列の両方の2つの矛盾する定義を与えていると考えてください。あるケースでは、それはエンティティであり、parent_idは単にそのエンティティの値であるとJPAに伝えました。もう1つは、CHILDテーブルはエンティティではなく、CHILDテーブルとPARENTテーブルの間に外部キー関係を作成するために使用されることをJPAに伝えました。問題は、CHILDテーブルがすでに存在していることです。次に、エンティティを永続化するときに、parent_idが明示的にnull(設定されていない)であると伝えましたが、parent_idを更新して、親テーブルへの外部キー参照を設定する必要があることも伝えました。

    上記で説明した変更を使用してコードを変更しました。また、「マージ」ではなく「永続化」とも呼びました。

    これにより、3つのSQLクエリが発生しました

    insert into PARENT (ID) values (default)
    insert into CHILD (ID) values (default)
    update CHILD set parent_id=? where ID=?
    

    これはあなたが望むものを完全に反映しています。 PARENTエントリが作成されます。 CHILDエントリが作成され、CHILDレコードが更新されて、外部キーが正しく設定されます。

    代わりに注釈を追加する場合

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "parent_id", nullable = false)
    private List<Child> children;
    

    次に、子を挿入するときに次のクエリを実行します

    insert into CHILD (ID, parent_id) values (default, ?)
    

    したがって、FKを最初から適切に設定します。



    1. SQL Serverで「time」を「datetimeoffset」に変換する(T-SQLの例)

    2. ロック待機タイムアウトが例外を超えないようにする方法。

    3. 絵文字がデータベースノードjsmysqlに挿入されていません

    4. 設計によるSQLデッドロックゼロ-コーディングパターンはありますか?