web-dev-qa-db-ja.com

JPA 2.0 orphanRemoval = true VS削除カスケード

JPA 2.0 orphanRemoval属性について少し混乱しています。

JPAプロバイダーのDB生成ツールを使用して、特定のリレーションにON DELETE CASCADEを持つように基になるデータベースDDLを作成するときに必要だと思うと思います。

ただし、DBが存在し、リレーションに既にON DELETE CASCADEがある場合、これは削除を適切にカスケードするのに十分ではありませんか? orphanRemovalはさらに何をしますか?

乾杯

159

orphanRemovalON DELETE CASCADEとは関係ありません。

orphanRemovalは完全にORM固有のものです。 「親」エンティティから参照されなくなったときに削除される「子」エンティティをマークします。親エンティティの対応するコレクションから子エンティティを削除するとき。

ON DELETE CASCADEデータベース固有のものです。「親」行が削除されると、データベースの「子」行が削除されます。

245
axtavt

here の形式の例:

Employeeエンティティオブジェクトが削除されると、削除操作は参照されるAddressエンティティオブジェクトにカスケードされます。この点で、orphanRemoval=truecascade=CascadeType.REMOVEは同一であり、orphanRemoval=trueが指定されている場合、CascadeType.REMOVEは冗長です。

2つの設定の違いは、関係の切断に対する応答にあります。たとえば、アドレスフィールドをnullまたは別のAddressオブジェクトに設定する場合など。

  • orphanRemoval=trueが指定されている場合、切断されたAddressインスタンスは自動的に削除されます。これは、所有者オブジェクト(たとえば、Address)からの参照なしでは存在しないはずの依存オブジェクト(たとえば、Employee)をクリーンアップするのに役立ちます。

  • cascade=CascadeType.REMOVEのみが指定されている場合、関係の切断は削除操作ではないため、自動アクションは実行されません。

孤立した削除の結果として参照がぶら下がるのを避けるために、この機能はプライベートな非共有依存オブジェクトを保持するフィールドに対してのみ有効にする必要があります。

これがより明確になることを願っています。

77
forhas

コレクションから子エンティティを削除すると、その子エンティティもDBから削除されます。 orphanRemovalは、親を変更できないことも意味します。従業員がいる部門がある場合、その従業員を削除して別の部門に入れると、flush/commit(どちらが先でも)でDBからその従業員を誤って削除してしまいます。その親の子が存在する間、別の親に移行しないことが確実である限り、士気はorphanRemovalをtrueに設定することです。 orphanRemovalをオンにすると、カスケードリストにREMOVEも自動的に追加されます。

44
Onur

DDL ON DELETE CASCADEに相当するJPAマッピングはcascade=CascadeType.REMOVEです。孤立した削除とは、「親」エンティティとの関係が破棄されたときに依存エンティティが削除されることを意味します。たとえば、エンティティマネージャで明示的に削除せずに@OneToMany関係から子が削除された場合。

17
Heri

@GaryKの答えは絶対に素晴らしいです。説明を探してorphanRemoval = trueCascadeType.REMOVEを探して、理解するのに役立ちました。

まとめ:orphanRemoval = trueCascadeType.REMOVEと同じように機能しますONLY IFオブジェクトを削除し(entityManager.delete(object))、childsオブジェクトも削除したいです。

完全に異なる状況では、List<Child> childs = object.getChilds()のようなデータをフェッチし、orphanRemoval=trueを使用して子(entityManager.remove(childs.get(0))を削除すると、childs.get(0)に対応するエンティティがデータベースから削除されます。

4
pzeszko

孤立した削除は、次のシナリオでON DELETE CASCADEと同じ効果があります:-学生エンティティとガイドエンティティ間に単純な多対1の関係があり、多くの学生が同じガイドにマッピングでき、データベースにあるとしましょうstudentテーブルがFKとしてid_guideを持つような、StudentテーブルとGuideテーブル間の外部キー関係。

    @Entity
    @Table(name = "student", catalog = "helloworld")
    public class Student implements Java.io.Serializable {
     @Id
     @GeneratedValue(strategy = IDENTITY)
     @Column(name = "id")
     private Integer id;

    @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
    @JoinColumn(name = "id_guide")
    private Guide guide;

//親エンティティ

    @Entity
    @Table(name = "guide", catalog = "helloworld")
    public class Guide implements Java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = 9017118664546491038L;

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;

@Column(name = "name", length = 45)
private String name;

@Column(name = "salary", length = 45)
private String salary;


 @OneToMany(mappedBy = "guide", orphanRemoval=true) 
 private Set<Student> students = new  HashSet<Student>(0);

このシナリオでは、関係は、学生エンティティが関係の所有者であるため、オブジェクトグラフ全体を永続化するために、学生エンティティを保存する必要があります。

    Guide guide = new Guide("John", "$1500");
    Student s1 = new Student(guide, "Roy","ECE");
    Student s2 = new Student(guide, "Nick", "ECE");
    em.persist(s1);
    em.persist(s2);

ここでは、2つの異なる学生オブジェクトを使用して同じガイドをマッピングしています。CASCADE.PERSISTが使用されているため、オブジェクトグラフは以下のようにデータベーステーブルに保存されます(私の場合はMySql)

STUDENTテーブル:-

ID名部Id_Guide

1 Roy ECE 1

2ニックECE 1

GUIDEテーブル:-

ID NAME給与

1ジョン1500ドル

そして今、私は学生の一人を削除したい場合は、使用して

      Student student1 = em.find(Student.class,1);
      em.remove(student1);

学生レコードが削除されると、対応するガイドレコードも削除される必要があります。これは、StudentエンティティのCASCADE.REMOVE属性が表示される場所であり、その処理は識別子1の学生と対応するガイドオブジェクト(識別子1)。ただし、この例では、同じガイドレコードにマップされるもう1つの学生オブジェクトがあり、Guide EntityでorphanRemoval = true属性を使用しない限り、上記の削除コードは機能しません。

3
kunal

違いは:
-orphanRemoval = true:「子」エンティティは、参照されなくなったときに削除されます(その親は削除できません)。
-CascadeType.REMOVE:「子」エンティティは、「親」が削除された場合にのみ削除されます。

3
user3572554