web-dev-qa-db-ja.com

@ManyToOne JPAアソシエーションのCascadeType.ALLの意味は何ですか?

@ManyToOne関係の文脈でカスケードすることの意味を誤解したと思います。

ケース:

public class User {

   @OneToMany(fetch = FetchType.EAGER)
   protected Set<Address> userAddresses;

}

public class Address {

   @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
   protected User addressOwner;

}

cascade = CascadeType.ALLの意味は何ですか?たとえば、データベースから特定のアドレスを削除した場合、cascade = CascadeType.ALLを追加したことがデータにどのように影響しますか(User、推測)。

171
forhas

CascadeType.ALLの意味は、永続性がすべてのEntityManager操作(PERSIST, REMOVE, REFRESH, MERGE, DETACH)を関連エンティティに伝播(カスケード)することです。

Addressを削除すると、関連するUserも削除されるので、あなたの場合は悪い考えのようです。ユーザーは複数のアドレスを持つことができるので、他のアドレスは孤児になります。ただし、逆の場合(Userに注釈を付ける)は意味があります。あるアドレスが単一のユーザーにのみ属している場合は、そのユーザーが削除された場合にそのユーザーに属するすべてのアドレスの削除を伝搬するのが安全です。

ところで:あなたは、結合列がADDRESSテーブルにあるべきであることを永続化プロバイダに知らせるためにあなたのUsermappedBy="addressOwner"属性を追加したくなるかもしれません。

301
kostja

OpenJPAのドキュメントの例については、こちら を参照してください。 CascadeType.ALLはすべてのアクションを実行することを意味します。

見積もり:

CascadeType.PERSIST:エンティティを永続化するときは、このフィールドに保持されているエンティティも永続化します。フラッシュ中にEntityManagerが新しいエンティティを参照するフィールドを見つけ、そのフィールドでCascadeType.PERSISTが使用されていない場合はエラーになるため、このカスケード規則の自由な適用をお勧めします。

CascadeType.REMOVE:エンティティを削除するときは、このフィールドに保持されているエンティティも削除してください。

CascadeType.REFRESH:エンティティを更新するときに、このフィールドに保持されているエンティティも更新します。

CascadeType.MERGE:エンティティの状態をマージするときに、このフィールドに保持されているエンティティもマージします。

セバスチャン

42
seba.wagner

EJB3.0仕様 より:

カスケード注釈要素の使用は、操作の効果を関連するエンティティに伝播するために使用され得る。カスケード機能は、最も一般的には親子関係で使用されます。

Xが管理対象エンティティの場合、削除操作によって削除されます。 Xからこれらの他のエンティティーへの関係がcascade = REMOVEまたはcascade = ALLアノテーション要素値でアノテートされている場合、除去操作はXによって参照されるエンティティーにカスケードされます。

したがって、一言で言えば、CascadeType.Allで定義されたエンティティの関係は、永続、更新、マージ、削除など、親で発生するすべての永続イベントが確実に子に渡されるようにします。他のCascadeTypeオプションを定義すると、開発者はエンティティの関連付けが永続性をどのように処理するかをよりきめ細かく制御できます。

たとえば、List of pagesを含むBookオブジェクトがあり、このリストにpageオブジェクトを追加したとします。 BookとPageの間の関連を定義する@OneToManyアノテーションがCascadeType.Allとしてマークされている場合、Bookを永続化すると、Pageもデータベースに永続化されます。

17
Kevin Bowersox

この記事 と私の本で説明したように、 High-Performance Java PersistenceCascadeType.ALL@ManyToOneを使用しないでください エンティティ状態遷移 は親から伝播する必要があるためエンティティを子のものに。

@ManyToOne側は、基礎となるFKをマップする必要があるため、常にChildアソシエーションです。

したがって、CascadeType.ALL@ManyToOneアソシエーションから@OneToManyに移動します。これはmappedBy属性を使用する必要があります 多対マッピング 。 `

16
Vlad Mihalcea

JPA 2.0では、ユーザーエンティティからアドレスを削除した場合にそのアドレスを削除する場合は、orphanRemoval=trueに(CascadeType.REMOVEではなく)@OneToManyを追加できます。

orphanRemoval=trueCascadeType.REMOVEの間の詳しい説明はここ です

9
Emilien Brigand

単にuserに割り当てられたアドレスを削除し、Userエンティティクラスに影響を与えたくない場合は、次のようにしてください。

@Entity
public class User {
   @OneToMany(mappedBy = "adressOwner", cascade = CascadeType.ALL)
   protected Set<Address> userAddresses = new HashSet<>();
}

@Entity 
public class Adresses {
   @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "user_id")
   protected User adressOwner;
}

こうすれば、アノテーションでフェッチを使うことを心配する必要はありません。しかし、ユーザーを削除するときは、ユーザーオブジェクトへの接続アドレスも削除することを忘れないでください。

1
szachMati