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

2022-08-31 10:13:53

假设我有两个实体:组和用户。每个用户都可以是多个组的成员,每个组可以有多个用户。

@Entity
public class User {
    @ManyToMany
    Set<Group> groups;
    //...
}

@Entity
public class Group {
    @ManyToMany(mappedBy="groups")
    Set<User> users;
    //...
}

现在我想删除一个组(假设它有很多成员)。

问题是,当我在某个组上调用 EntityManager.remove() 时,JPA 提供程序(在我的情况下是 Hibernate)不会从联接表中删除行,并且由于外键约束,删除操作失败。在User上调用demove()工作正常(我想这与拥有关系的一面有关)。

那么在这种情况下,我该如何删除组呢?

我能想到的唯一方法是加载组中的所有用户,然后为每个用户从他的组中删除当前组并更新用户。但是对我来说,对组中的每个用户调用update()只是为了能够删除这个组,这似乎很荒谬。


答案 1
  • 关系的所有权取决于您将 'mappedBy' 属性放置到批注中的位置。您放置“mappedBy”的实体不是所有者的实体。双方都没有机会成为所有者。如果您没有“删除用户”用例,则可以简单地将所有权移动到实体,因为目前是所有者。GroupUser
  • 另一方面,你没有问过它,但有一件事值得知道。和 不相互组合。我的意思是,从Group1.users中删除User1实例后,User1.groups集合不会自动更改(这对我来说非常令人惊讶),groupsusers
  • 总而言之,我建议你决定谁是老板。让我们说是老板。然后,在删除用户时,关系用户组将自动更新。但是,在删除组时,您必须自己处理删除关系,如下所示:User

entityManager.remove(group)
for (User user : group.users) {
     user.groups.remove(group);
}
...
// then merge() and flush()

答案 2

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

@PreRemove
private void removeGroupsFromUsers() {
    for (User u : users) {
        u.getGroups().remove(this);
    }
}

请记住,要使此操作生效,组必须具有更新的用户列表(不会自动完成)。因此,每次将组添加到用户实体中的组列表时,还应将用户添加到组实体中的用户列表。


推荐