web-dev-qa-db-ja.com

JPA Hibernateの多対多のカスケード

JPA 2.0と休止状態を使用しています。次のように、ユーザークラスとグループクラスがあります。

public class User implements Serializable {
    @Id
    @Column(name="USER_ID")
    private String userId;

    @ManyToMany
    @JoinTable(name = "USER_GROUP",
               joinColumns = {
                   @JoinColumn(name = "GROUP_ID")
               },
               inverseJoinColumns = {
                   @JoinColumn(name = "USER_ID")
               }
    )
    private Set<Group> groupList;

    //get set methods
}

public class Group
{
    @Id
    @Column(name="GROUP_ID")
    private String groupId;

    @ManyToMany(mappedBy="groupList")
    private Set<User> memberList;
    //get set methods
}

そして、ユーザーとグループを作成し、ユーザーをグループに割り当てます。

私が持ちたいのは、グループを削除すると、グループが(もちろん)削除され、グループが持つすべてのユーザーとグループの関係がUSER_GROUP結合テーブルから自動的に削除されますが、ユーザー自体はUSERテーブル。

上記のコードでは、グループを削除するとGROUPテーブルの行のみが削除され、ユーザーはUSER_GROUP結合テーブルで削除されたグループへのエントリを保持します。

このようにカスケードをUserクラスに入れた場合:

@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "USER_GROUP",
joinColumns =
{
    @JoinColumn(name = "GROUP_ID")
},
inverseJoinColumns =
{
    @JoinColumn(name = "USER_ID")
})
private Set<Group> groupList;

グループを削除すると、ユーザーも削除されます!

私が望むものを達成する方法はありますか?

48
Hery

マッピング方法では、Userはリレーションシップの管理側であるため、結合テーブルの更新を担当します。

JoinTableマッピングをUserからGroupに変更し、groupListUserプロパティをmappedBy属性を持つように変更します。これにより、グループが関係の管理側に変更され、グループへの永続/更新呼び出しが行われ、結合テーブルが管理されます。

ただし、グループをユーザーに追加し、ユーザーを保存して続行することはできません。代わりに、グループにユーザーを追加し、グループを保存して変更を確認する必要がありますが、双方向の多対多を持つことで、とにかくその関係を密接に管理できることを願っています。

38
digitaljoel

別の角度から問題を見る:

FK制約を多対多のマッピングテーブルに追加できます。実際、データ整合性の理由から、DBには常にFKが必要です。この場合、たとえば、マッピングテーブルに孤立行を静かに残しながら、少なくともユーザーを削除できませんでした。

FKがある場合は、制約でon カスケード参照アクションの削除 を指定できます。DBは、要求されたように、エンティティではなくマッピングテーブルの自動削除を管理します。

5
Pierre Henry

既に示したように、ユーザー側からカスケードする必要がない場合は、関係のグループ所有者を作成します。

次に、cascade=CascadeType.MERGEグループを削除するときにユーザーをカスケード削除しないようにします。

4
atidafi

このようなことができます

@PreRemove
private void removeMembers() {
    this.memberList.clear();
}
1