如何防止在添加新条目时从双向 ManyToMany 集合中检索所有条目

How to prevent retrieval of all entries from bidirectional ManyToMany collection while adding new entry

我想知道如何在向该集合添加新条目时阻止从双向 ManyToMany 集合中检索所有条目。 我有 User 实体,它与 UserGroup 实体具有双向关系。 当我在 User 实体中添加组时,它会将 User 添加到组中,并且 UserGroup 是父级。问题是,如果我向用户添加很多组(比如说 20 个),那么用户也会被添加到每个组,并且从每个组中检索所有用户(每个组超过 100 个)。它使交易花费大量时间并显示出明显的滞后,而我只想将 UserGroup 插入用户的 userGroups 集合而无需从这些组中选择其他用户。

User.java

@ManyToMany(mappedBy = "users")
private Set<UserGroup> userGroups;

public void addGroup(UserGroup userGroup){
this.userGroups.add(userGroup);
userGroup.addUser(this);
}

UserGroup.java

@ManyToMany
@JoinTable(name = "group_users", joinColumns = @JoinColumn(name = "group_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id"))
private Set<User> users;

public void addUser(User user) {
   this.users.add(user);
}

使用的方法

@Transactional
public void addGroupsToUser(UserAddGroupsCommand userAddGroupsCommand, String username) {
    User user = userRepository.findByUsername(username);
    if (user != null) {
        List<UserGroup> userGroupList = userGroupRepository.findAllById(userAddGroupsCommand.getId());
        for (UserGroup userGroup : userGroupList) {
            user.addGroup(userGroup);
        }
        userRepository.save(user);
    }
}

所以我可以在控制台中看到,所有加入 table 条目都被选择用于我正在迭代的组

已编辑:这是执行的代码,我不确定为什么。

select users0_.group_id as group_id1_0_0_, users0_.user_id as user_id2_0_0_, user1_.id as id1_7_1_ 
from group_users users0_ 
inner join User user1_ on users0_.user_id=user1_.id 
where users0_.group_id=?

如果您不需要知道哪些用户在一个组中(在应用程序中显示),则进行单向映射。从用户组 class 中删除 Set<User> users

在用户 class 中使用 @JoinTable 代替 mappedBy:

@ManyToMany
@JoinTable(name = "group_users", 
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "group_id"))
private Set<UserGroup> userGroups;

public void addGroup(UserGroup userGroup){
    this.userGroups.add(userGroup);
}

尝试自定义查询以获得更好的性能

from UserGroup g left join fetch g.users where g.id in :IDS

这样每个组中的用户将在一个查询中加载,而不是在 N+1 个查询中加载。

更改 @ManyToMany(FetchType.EAGER) 效率不高,因为用户将始终加载 UserGroup,在不使用时也是如此。

使用 @EntityGraphjoin fetch 查询相同。