假设我有两个实体:Group和User . 每个用户都可以是许多组的成员,每个组可以拥有许多用户 .
@Entity
public class User {
@ManyToMany
Set<Group> groups;
//...
}
@Entity
public class Group {
@ManyToMany(mappedBy="groups")
Set<User> users;
//...
}
现在我想删除一个组(假设它有很多成员) .
问题是当我在某些Group上调用EntityManager.remove()时,JPA提供程序(在我的情况下是Hibernate) does not remove rows from join table 并且由于外键约束而删除操作失败 . 在User上调用remove()工作正常(我猜这与拥有关系的一方有关) .
那么在这种情况下如何删除组呢?
我能想到的唯一方法是加载组中的所有用户,然后为每个用户从他的组中删除当前组并更新用户 . 但是,为了能够删除该组,对组中的每个用户调用update()似乎很荒谬 .
7 回答
这是一个很好的解决方案 . 最好的部分是在SQL方面 - 对任何级别的微调很容易 .
我使用MySql和MySql Workbench来删除所需的外键 .
这对我有用:
另外,标记方法@Transactional(org.springframework.transaction.annotation.Transactional),这将在一个会话中完成整个过程,节省一些时间 .
关系的所有权取决于将'mappedBy'属性放置到注释的位置 . 您放置'mappedBy'的实体是非所有者的实体 . 有一个'delete user'用例你可以简单地将所有权移动到
Group
实体,因为目前User
是所有者 .另一方面,你没有问过这个问题,但有一件事值得一提 .
groups
和users
彼此不相合 . 我的意思是,从Group1.users中删除User1实例后,User1.groups集合不会自动更改(这对我来说非常令人惊讶),总而言之,我建议你决定谁是主人 . 假设
User
是所有者 . 然后,当删除用户时,关系用户组将自动更新 . 但是当删除一个组时,你必须像下面这样自己删除这个关系:以下适用于我 . 将以下方法添加到不是关系所有者的实体(组)
请记住,要使其工作,该组必须具有更新的用户列表(不会自动完成) . 因此,每次将组添加到用户实体中的组列表时,还应将用户添加到组实体中的用户列表 .
我找到了一个可能的解决方案,但是......我不知道这是不是一个好的解决方案 .
我试过这个并且它有效 . 删除Role时,也会删除关系(但不删除Permission实体),删除Permission时,也会删除与Role的关系(但不删除Role实例) . 但是我们两次映射单向关系,两个实体都是关系的所有者 . 这会给Hibernate带来一些问题吗?哪种类型的问题?
谢谢!
上面的代码来自另一个post相关 .
作为JPA / Hibernate解决方案的替代方法:您可以在连接表上的foregin键的数据库定义中使用CASCADE DELETE子句,例如(Oracle语法):
这样,DBMS本身会在您删除组时自动删除指向该组的行 . 无论是从Hibernate / JPA,JDBC,在DB中手动还是以任何其他方式进行删除,它都有效 .
所有主要的DBMS(Oracle,MySQL,SQL Server,PostgreSQL)都支持级联删除功能 .
为了它的 Value ,我使用EclipseLink 2.3.2.v20111125-r10461,如果我有@ManyToMany单向关系,我会观察你描述的问题 . 但是,如果我将其更改为双向@ManyToMany关系,我可以从非拥有方删除实体,并且JOIN表会相应更新 . 这都不使用任何级联属性 .