JPAのCascadeType.REMOVEとorphanRemovalの違いは何ですか?


100

違いは何ですか

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

そして

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

この例はJava EEチュートリアルからのものですが、詳細はまだわかりません。


孤立した削除とは、「親」エンティティとの関係が破壊されると、依存エンティティが削除されることを意味します。
Rahul Tripathi 2013

1
概念を説明する可能性のあるテストケースを作成します。
Martin Andersson

回答:


152

ここから:-

カスケード削除

CascadeType.REMOVE(またはREMOVEを含むCascadeType.ALL)で参照フィールドをマークすると、そのフィールドによって参照されるエンティティオブジェクトに削除操作が自動的にカスケードされることを示します(コレクションフィールドによって複数のエンティティオブジェクトを参照できます)。

@Entity
class Employee {
     :
    @OneToOne(cascade=CascadeType.REMOVE)
    private Address address;
     :
}

孤立した削除

JPA 2は、@ OneToOneおよび@OneToManyアノテーションのorphanRemoval要素を使用して指定できる追加のより積極的な削除カスケードモードをサポートしています。

@Entity
class Employee {
     :
    @OneToOne(orphanRemoval=true)
    private Address address;
     :
}

差:-

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

  • 場合orphanRemoval =真 ISは、指定された切断Addressインスタンスは自動的に削除されます。これは、所有者オブジェクト(従業員など)からの参照なしでは存在してはならない依存オブジェクト(住所など)をクリーンアップするのに役立ちます。
  • cascade = CascadeType.REMOVEのみが指定されている場合、関係の切断は削除
    操作ではないため、自動アクションは実行されません。

87

違いを理解するための簡単な方法CascadeType.REMOVEとはorphanRemoval=true

孤立した削除の場合:を呼び出すsetOrders(null)と、関連するOrderエンティティがdbから自動的に削除されます。

カスケードの削除の場合:を呼び出したsetOrders(null)場合、関連するOrderエンティティはdbから自動的に削除されません


2
削除===削除
Abdull '15年

9

子エンティティと親エンティティがあるとします。親は複数の子供を持つことができます。

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

orphanRemovalはORMの概念であり、子が孤立しているかどうかを示します。また、データベースからも削除する必要があります。

親からアクセスできない場合、子は孤立します。たとえば、Personオブジェクトセットを削除する(空のセットに設定する)か、または新しいセットに置き換えると、親は古いセットの子にアクセスできなくなり、子は孤立し、子は運命づけられますデータベースからも削除されました。

CascadeType.REMOVEはデータベースレベルの概念であり、親が削除されたかどうかを通知し、子テーブル内の関連するすべてのレコードを削除する必要があります。


2

実際の違いは、データを更新しようとしているのか(PATCH)、データ全体を置き換えようとしているのか(PUT)です。

あなたが削除しましょうcustomer使用するよりcascade=REMOVEも、意図と便利なように見えるその顧客の注文を削除します。

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

ここで、を更新するcustomerorphanRemoval="true"、以前のすべての注文が削除され、提供された注文に置き換えられます。(PUTに関してREST API

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

orphanRemoval古い注文がなければ維持されます。(PATCHに関してREST API


1

この質問は非常に一般的であるため、この回答は私がブログに書いたこの記事に基づいています。

CascadeType.REMOVE

CascadeType.REMOVEあなたが明示的に設定することができます戦略:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

またはCascadeType.ALL戦略から暗黙的に継承します:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

remove親エンティティから子エンティティに操作を伝播できます。

したがって、親Postエンティティとそのcommentsコレクションをフェッチし、エンティティを削除すると、次のようになりpostます。

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

Hibernateは3つの削除ステートメントを実行します。

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

PostComment子エンティティがあるため、削除されたCascadeType.REMOVE私たちは、同様の子実体を削除かのように行動した戦略、。

孤児除去戦略

孤児除去戦略。これは、orphanRemoval属性を介して設定する必要があります。

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

コレクションから子エンティティを削除するときに、子テーブル行を削除できます。

したがって、Postエンティティをそのcommentsコレクションとともにロードし、最初のエンティティをコレクションから削除すると、次のようPostCommentになりcommentsます。

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

Hibernateは関連するpost_commentテーブル行に対してDELETEステートメントを実行します:

DELETE FROM post_comment 
WHERE id = 2

このトピックの詳細については、こちらの記事もご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.