如何从 @ManyToMany 关系中删除与 JPA 和 Hibernate 中的许多子对象的子对象

Posted

技术标签:

【中文标题】如何从 @ManyToMany 关系中删除与 JPA 和 Hibernate 中的许多子对象的子对象【英文标题】:How to remove child objects from a @ManyToMany relation with lots of children in JPA and Hibernate 【发布时间】:2017-10-19 17:32:49 【问题描述】:

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

@Entity
public class User 
    @ManyToMany
    Set<Organization> organizations;
    //...


@Entity
public class Organization 
    @ManyToMany(mappedBy="organizations")
    Set<User> users;
    //...

现在,我想删除一个组织(假设它有 1000 个成员)。 当用户的组织很少时,这段代码就可以了:

void removeOrgFromUser(Integer userId,Integer orgId)
    User user = session.load(User.class, userId);
    for (Organization org : user.organizations) 
        if(org.getId().equals(orgId))
            user.organizations.remove(org);
    
    session.update(user);

但当组织数为 10,000 时,此解决方案的性能不佳。

我该如何解决?

【问题讨论】:

从连接表中删除行。 我想用 hibernate 或 hql 做到这一点, @Antoniossss 使用 sql native? 是的,使用带有 user_id 和 departament_id 标准的准备好的语句 从这里尝试 JBNizet 的答案:***.com/questions/8699153/… 在删除组织之前清除组织中的用户集合。另一种方法是按照@Antoniossss 的建议通过 SQL。 【参考方案1】:

如果您有超过 50 或 100 个子实体,则不应映射集合。

因此,@OneToMany 具有误导性,因为实际上@OneToFew 更有意义。因此,当 many 表示 1000 或 10000 时,映射这样的集合就成了一个真正的性能问题。

在这种情况下,只需断开 @ManyToMany 关联,以便映射连接表 UserOrganization

在这种情况下,您只需要连接表上的 2 个 @ManyToOne 关联,并且您可以像这样发出批量删除查询:

delete from UserOrganization uo
where uo.organization = :organization

就是这样!

【讨论】:

以上是关于如何从 @ManyToMany 关系中删除与 JPA 和 Hibernate 中的许多子对象的子对象的主要内容,如果未能解决你的问题,请参考以下文章

如何删除 JPA @ManyToMany 关系中的记录?

如何在 Nest.js 中删除 @ManyToMany 关系中的数据

多对多manytomany

Symfony数据夹具与ManyToMany的关系

如何使用 JPQL 删除 ManyToMany 项目?

Django:如何从 ManyToMany 迁移到 ForeignKey?