私は同様の質問をたくさん見ていますが、それを結びつける決定的なものは見つかりませんでした。JPAでのカスケード削除@OneToManyとデータベースカスケードの外部キーの削除
JPAを使用する場合、@OneToMany関係がある場合は、REMOVE
操作をカスケードするように指定できます。同時に、キーベース行が削除された場合に実行するアクションでデータベースに外部キーを指定することができます。
JPA例:データベースで
@Entity
public class Parent {
@Id
private Long id;
@OneToMany(cascade = {CascadeType.REMOVE})
private List<Child> children;
// getters, setters...
}
@Entity
public class Child {
@Id
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = parent_id, nullable = false)
private Parent parent;
// getters, setters...
}
、Child
テーブルは、次にParent
のid
列に対する外部キー制約とカラムparent_id
を有するであろう。
削除時にカスケードするための外部キー制約で可能なアクションは、delete
,set to null
およびdo nothing
です。これにより、以下のシナリオの組み合わせが得られます。
JPA | cascade | no cascade | | remove | remove | DB FK | | | -----------+---------+------------| delete | A | D | -----------+---------+------------| set null | B | E | -----------+---------+------------| do nothing | C | F | -----------+---------+------------+
- A:カスケードは、JPAで親に電話を削除し、彼らはへの外部キーを持つ親行の削除時にデータベースに子供を削除します。
- B:JPAでカスケード削除を行い、親削除のデータベースで子テーブルの外部キー列をnullに設定します。 @JoinColumnの
nullable
および/またはの@ManyToOne
は、おそらくこの場合はtrue/falseである必要があります。 - C:JPAでカスケード削除します。データベースで外部キーを削除しても何も実行しません。
- D:JPAでカスケード削除を実行せず、データベース内の親のカスケード削除を実行しないでください。
- E:JPAで削除をカスケードしないでください。親deleteのデータベースでChildテーブルの外部キー列をnullに設定してください。
- F:JPAで削除をカスケードしないでください。外部キーを削除しても、データベースは何も実行しないでください。
です。
これらのシナリオのどれが例外につながりますか?図Cの場合。 Parent
インスタンスをEntityManager
経由で削除すると、そのインスタンスでコールが行われた後、コレクションプロパティのChild
インスタンスにカスケードされます。しかし、関連する子を最初に削除せずにデータベースから親を削除しようとすると、外部キー違反が発生します。これは正しいです?他の不具合のシナリオはありますか? Woud原因は、基盤となるDBからすでに削除されている永続性からエンティティを削除しようとすると問題が発生しますか?
これは、EntityManagerキャッシュをデータベースと一貫性のない状態にしますか?私はそれがDとEだと思っています。このような場合は、子リストのインスタンスに対してremove()
を自分で呼び出す必要があります。
JPAレイヤーとデータベースの両方でデータの整合性を強化するために使用する設定はどれですか? Aはトリックを行いますか?データベース自体が親を削除する際に外部キー列をnullに設定し、JPAが子インスタンスを削除できるため、Bも機能すると思います。