为了账号安全,请及时绑定邮箱和手机立即绑定

如何在JPA中删除具有ManyToMany关系的实体(以及相应的联接表行)?

如何在JPA中删除具有ManyToMany关系的实体(以及相应的联接表行)?

牧羊人nacy 2019-12-12 14:48:18
假设我有两个实体:“组”和“用户”。每个用户可以是多个组的成员,每个组可以有多个用户。@Entitypublic class User {    @ManyToMany    Set<Group> groups;    //...}@Entitypublic class Group {    @ManyToMany(mappedBy="groups")    Set<User> users;    //...}现在,我要删除一个组(假设它有很多成员)。问题是,当我在某个组上调用EntityManager.remove()时,JPA提供程序(在我的情况下为Hibernate)不会从联接表中删除行,并且由于外键约束,删除操作也会失败。在User上调用remove()可以正常工作(我想这与拥有关系的一方有关)。那么在这种情况下如何删除组?我想出的唯一方法是加载组中的所有用户,然后为每个用户从其组中删除当前组并更新用户。但是,对于该组中的每个用户调用update()只是为了能够删除该组,这似乎很荒谬。
查看完整描述

3 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

关系的所有权取决于将“ mappedBy”属性放置在注释中的位置。您放置“ mappedBy”的实体不是所有者。双方都没有机会成为所有者。如果您没有“删除用户”用例,则可以简单地将所有权移至Group实体,因为当前User是所有者。

另一方面,您没有问过这个问题,但是有一件事值得知道。的groups和users不与彼此组合。我的意思是,从Group1.users中删除User1实例后,User1.groups集合不会自动更改(这对我来说很令人惊讶),

总而言之,我建议您确定谁是所有者。假设User是所有者。然后,在删除用户时,关系用户组将自动更新。但是,在删除组时,您必须像这样删除自己的关系:

entityManager.remove(group)

for (User user : group.users) {

     user.groups.remove(group);

}

...

// then merge() and flush()


查看完整回答
反对 回复 2019-12-12
?
慕森卡

TA贡献1806条经验 获得超8个赞

以下对我有用。将以下方法添加到不是关系(组)所有者的实体


@PreRemove

private void removeGroupsFromUsers() {

    for (User u : users) {

        u.getGroups().remove(this);

    }

}

请记住,要使此功能起作用,组必须具有更新的用户列表(不会自动完成)。因此,每次将“网上论坛”添加到“用户”实体中的群组列表时,也应将“用户”添加到“群组”实体中的用户列表中。


查看完整回答
反对 回复 2019-12-12
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

我找到了可能的解决方案,但是...我不知道这是否是一个好的解决方案。


@Entity

public class Role extends Identifiable {


    @ManyToMany(cascade ={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})

    @JoinTable(name="Role_Permission",

            joinColumns=@JoinColumn(name="Role_id"),

            inverseJoinColumns=@JoinColumn(name="Permission_id")

        )

    public List<Permission> getPermissions() {

        return permissions;

    }


    public void setPermissions(List<Permission> permissions) {

        this.permissions = permissions;

    }

}


@Entity

public class Permission extends Identifiable {


    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})

    @JoinTable(name="Role_Permission",

            joinColumns=@JoinColumn(name="Permission_id"),

            inverseJoinColumns=@JoinColumn(name="Role_id")

        )

    public List<Role> getRoles() {

        return roles;

    }


    public void setRoles(List<Role> roles) {

        this.roles = roles;

    }

我已经尝试过了,并且有效。删除角色时,关系也将被删除(但不删除Permission实体);删除权限时,与角色的关系也将被删除(但不删除Role实例)。但是我们两次映射单向关系,并且两个实体都是该关系的所有者。这会导致一些问题休眠吗?哪种类型的问题?


查看完整回答
反对 回复 2019-12-12
  • 3 回答
  • 0 关注
  • 1061 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信