@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
、推測)。
CascadeType.ALL
の意味は、永続性がすべてのEntityManager
操作(PERSIST, REMOVE, REFRESH, MERGE, DETACH
)を関連エンティティに伝播(カスケード)することです。
Address
を削除すると、関連するUser
も削除されるので、あなたの場合は悪い考えのようです。ユーザーは複数のアドレスを持つことができるので、他のアドレスは孤児になります。ただし、逆の場合(User
に注釈を付ける)は意味があります。あるアドレスが単一のユーザーにのみ属している場合は、そのユーザーが削除された場合にそのユーザーに属するすべてのアドレスの削除を伝搬するのが安全です。
ところで:あなたは、結合列がADDRESSテーブルにあるべきであることを永続化プロバイダに知らせるためにあなたのUser
にmappedBy="addressOwner"
属性を追加したくなるかもしれません。
OpenJPAのドキュメントの例については、こちら を参照してください。 CascadeType.ALL
はすべてのアクションを実行することを意味します。
見積もり:
CascadeType.PERSIST:エンティティを永続化するときは、このフィールドに保持されているエンティティも永続化します。フラッシュ中にEntityManagerが新しいエンティティを参照するフィールドを見つけ、そのフィールドでCascadeType.PERSISTが使用されていない場合はエラーになるため、このカスケード規則の自由な適用をお勧めします。
CascadeType.REMOVE:エンティティを削除するときは、このフィールドに保持されているエンティティも削除してください。
CascadeType.REFRESH:エンティティを更新するときに、このフィールドに保持されているエンティティも更新します。
CascadeType.MERGE:エンティティの状態をマージするときに、このフィールドに保持されているエンティティもマージします。
セバスチャン
EJB3.0仕様 より:
カスケード注釈要素の使用は、操作の効果を関連するエンティティに伝播するために使用され得る。カスケード機能は、最も一般的には親子関係で使用されます。
Xが管理対象エンティティの場合、削除操作によって削除されます。 Xからこれらの他のエンティティーへの関係がcascade = REMOVEまたはcascade = ALLアノテーション要素値でアノテートされている場合、除去操作はXによって参照されるエンティティーにカスケードされます。
したがって、一言で言えば、CascadeType.All
で定義されたエンティティの関係は、永続、更新、マージ、削除など、親で発生するすべての永続イベントが確実に子に渡されるようにします。他のCascadeType
オプションを定義すると、開発者はエンティティの関連付けが永続性をどのように処理するかをよりきめ細かく制御できます。
たとえば、List of pagesを含むBookオブジェクトがあり、このリストにpageオブジェクトを追加したとします。 BookとPageの間の関連を定義する@OneToMany
アノテーションがCascadeType.All
としてマークされている場合、Bookを永続化すると、Pageもデータベースに永続化されます。
この記事 と私の本で説明したように、 High-Performance Java Persistence 、CascadeType.ALL
で@ManyToOne
を使用しないでください エンティティ状態遷移 は親から伝播する必要があるためエンティティを子のものに。
@ManyToOne
側は、基礎となるFKをマップする必要があるため、常にChildアソシエーションです。
したがって、CascadeType.ALL
を@ManyToOne
アソシエーションから@OneToMany
に移動します。これはmappedBy
属性を使用する必要があります 多対マッピング 。 `
JPA 2.0では、ユーザーエンティティからアドレスを削除した場合にそのアドレスを削除する場合は、orphanRemoval=true
に(CascadeType.REMOVE
ではなく)@OneToMany
を追加できます。
orphanRemoval=true
とCascadeType.REMOVE
の間の詳しい説明はここ です 。
単に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;
}
こうすれば、アノテーションでフェッチを使うことを心配する必要はありません。しかし、ユーザーを削除するときは、ユーザーオブジェクトへの接続アドレスも削除することを忘れないでください。