あなたの関係は双方向である必要はありません。ここのコメントにはいくつかの誤った情報があります。
また、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を最初から適切に設定します。