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

时间:2019-02-27 00:20:06

标签: java hibernate spring-data-jpa many-to-many bidirectional-relation

我想知道如何防止在双向ManyToMany集合中检索所有条目,同时在该集合中添加新条目。 我有用户实体,它与UserGroup实体具有双向关系。 当我在用户实体中添加组时,会将用户添加到组中,并且UserGroup是父级。问题是,如果我向用户添加了很多组(比如说20个),那么用户也会添加到每个组中,并且从每个组中检索到所有用户(每个组100个以上)。我只想将UserGroup插入User的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);
    }
}

所以我可以在控制台中看到,我要访问的组的所有联接表条目均已选择

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

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=?

2 个答案:

答案 0 :(得分:1)

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

在User类中,使用@JoinTable而不是mappingBy:

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

答案 1 :(得分:0)

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

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

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

更改@ManyToMany(FetchType.EAGER)效率不高,因为用户总是会被加载UserGroup,甚至在不使用时也是如此。

使用@EntityGraphjoin fetch查询相同。