次のような単方向 _@ManyToOne
_の関係があるとします。
_@Entity
public class Parent implements Serializable {
@Id
@GeneratedValue
private long id;
}
@Entity
public class Child implements Serializable {
@Id
@GeneratedValue
private long id;
@ManyToOne
@JoinColumn
private Parent parent;
}
_
親Pと子Cがある場合1... Cn Pを参照し直しますが、JPAには子Cを自動的に削除するきれいできれいな方法がありますか1... Cn Pが削除されたとき(つまりentityManager.remove(P)
)?
私が探しているのは、SQLの_ON DELETE CASCADE
_に似た機能です。
JPAの関係は、親と子を双方向で関連付けない限り、常に単方向です。親から子へのカスケードREMOVE操作では、親から子へのリレーションが必要になります(逆ではありません)。
したがって、これを行う必要があります。
@ManyToOne
_関係を双方向の_@ManyToOne
_または単方向の_@OneToMany
_に変更します。その後、 _EntityManager.remove
_ が親と子を削除するように、REMOVE操作をカスケードできます。 orphanRemoval
をtrueに指定して、親コレクションの子エンティティがnullに設定されている場合、孤立した子を削除する、つまり、子が親の子に存在しない場合は削除することもできますコレクション。ON DELETE CASCADE
_として指定します。永続コンテキストを更新する必要があるため、 EntityManager.clear()
を呼び出した後、 EntityManager.remove(parent)
を呼び出す必要があります-子エンティティはデータベースから削除された後、永続コンテキストに存在することになっています。JPAプロバイダーとしてhibernateを使用している場合、アノテーション@OnDeleteを使用できます。このアノテーションは、リレーションにトリガーON DELETE CASCADEを追加します。これは、子の削除をデータベースに委任します。
例:
public class Parent {
@Id
private long id;
}
public class Child {
@Id
private long id;
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
private Parent parent;
}
このソリューションでは、すべての子を自動的に削除するには、子から親への一方向の関係で十分です。このソリューションはリスナーなどを必要としません。また、DELETE FROM Parent WHERE id = 1のようなクエリは子を削除します。
次のような双方向の関係を作成します。
@Entity
public class Parent implements Serializable {
@Id
@GeneratedValue
private long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
private Set<Child> children;
}
単方向の@ManytoOneで、削除が期待どおりに機能しないことを確認しました。親を削除する場合、理想的には子も削除する必要がありますが、親のみが削除され、子は削除されず、孤立したままになります
使用されるテクノロジーは、Spring Boot/Spring Data JPA/Hibernateです。
スプリントブート:2.1.2.RELEASE
Spring Data JPA/Hibernateは、行.egを削除するために使用されます
parentRepository.delete(parent)
ParentRepositoryは、以下に示すように標準のCRUDリポジトリを拡張しますParentRepository extends CrudRepository<T, ID>
以下は私のエンティティクラスです
@Entity(name = “child”)
public class Child {
@Id
@GeneratedValue
private long id;
@ManyToOne( fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = “parent_id", nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private Parent parent;
}
@Entity(name = “parent”)
public class Parent {
@Id
@GeneratedValue
private long id;
@Column(nullable = false, length = 50)
private String firstName;
}