How to remove child objects from a @ManyToMany relation with lots of children in JPA and Hibernate

Tags: , , , ,



Let’s say I have two entities: Organization and User. Every user can be a member of many organizations and every organization can have many users.

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

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

Now, I want to remove an organization (let’s say it has 1000 members). When the user has few organizations, this code is ok:

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);
}

But when organization count is 10,000, this solution does not have good performance.

How can I fix it?

Answer

If you have more than 50 or 100 child entities, you shouldn’t map a collection.

Therefore, @OneToMany is misleading because, in reality, @OneToFew makes more sense. So, when many means 1000 or 10000, mapping such a collection becomes a real performance problem.

In this case, just break the @ManyToMany association so that you map the join table UserOrganization.

In this case, you just need the 2 @ManyToOne associations on the join table, and, you can just issue a bulk delete query like this:

delete from UserOrganization uo
where uo.organization = :organization

That’s it!



Source: stackoverflow