@ManyToMany 保存关系在一个方向上只能使用一次

@ManyToMany saving relations is available only one time in one direction

我将尝试在我的 SpringBoot 应用程序中创建 @ManyToMany 关系。 我使用 JPARespository,我创建了 2 个模型:

用户

@Entity(name = "User")
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    @ManyToMany//(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @LazyCollection(value = LazyCollectionOption.FALSE)
    @JoinTable(
            name = "users_groups",
            joinColumns = @JoinColumn(name = "users_id"),
            inverseJoinColumns = @JoinColumn(name = "groups_id")
    )
    private Set<UGroup> groups;

    public User() {
        this.groups = new HashSet<>();
    }

    public void addGroup(UGroup uGroup) {
        this.groups.add(uGroup);
        uGroup.users.add(this);
    }

    public void removeGroup(UGroup uGroup) {
        this.groups.remove(uGroup);
        uGroup.users.remove(this);
    }
}

U组

@Data
@Entity(name = "UGroup")
@Table(name = "groups")
public class UGroup {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    @ManyToMany(mappedBy = "groups", cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @LazyCollection(value = LazyCollectionOption.FALSE)
    public Set<User> users;

    public UGroup() {
        this.users = new HashSet<>();
    }

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

    public void removeUser(User user) {
        this.users.remove(user);
        user.getGroups().remove(this);
    }
}

我通过 DataConfiguration 加载启动数据 class:

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        User user = new User();
        user.setName("Damian");
        userRepository.save(user);

        user = new User();
        user.setName("Marta");
        userRepository.save(user);

        user = new User();
        user.setName("Natalia");
        userRepository.save(user);

        UGroup uGroup = new UGroup();
        uGroup.setName("Mieszkanie");
        uGroup = uGroupRepository.save(uGroup);

        user = userRepository.findById(1).get();
        user.addGroup(uGroup);
        user = userRepository.save(user);

        // unable to execute
        /*
        user = userRepository.findById(2).get();
        user.addGroup(uGroup);
        user = userRepository.save(user);
         */

        // unable to execute 2
        /*
        uGroup = uGroupRepository.findById(4).get();
        uGroup.addUser(userRepository.findById(3).get());
        uGroup = uGroupRepository.save(uGroup);
         */
    }

当我只为 1 个用户执行插入组时,一切都很好。 虽然当我尝试为 1 和 2 个用户执行插入组或为组插入 3 个用户时,它会导致 java.lang.WhosebugError: null 异常。

不知道哪里出错了。任何人都可以帮助我并解释我应该在哪里以及为什么我应该改变某些东西吗? 提前致谢。

使用 Join Table,可以双向映射 ManyToMany relation.These 是修改后的实体 类

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity(name = "User")
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Set<UGroup> getGroups() {
        return groups;
    }

    public void setGroups(Set<UGroup> groups) {
        this.groups = groups;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany(mappedBy = "users",cascade = CascadeType.ALL)
    @LazyCollection(value = LazyCollectionOption.FALSE)
    private Set<UGroup> groups=new HashSet<UGroup>();

    public User() {
    }

    public void addGroup(UGroup uGroup) {
        this.groups.add(uGroup);
        uGroup.users.add(this);
    }

    public void removeGroup(UGroup uGroup) {
        this.groups.remove(uGroup);
        uGroup.users.remove(this);
    }
}

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity(name = "UGroup")
@Table(name = "groups")
public class UGroup {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "USER_GROUP_MAP" ,joinColumns = @JoinColumn(name="GROUP_ID",referencedColumnName = "ID")
            ,inverseJoinColumns = @JoinColumn(name="USER_ID",referencedColumnName = "ID"))
    @LazyCollection(value = LazyCollectionOption.FALSE)
    public Set<User> users=new HashSet<>();

    public UGroup() {
    }

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

    public void removeUser(User user) {
        this.users.remove(user);
        user.removeGroup(this);
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }
}

对于多对多关系,加入 table 是必要的。

SELECT * FROM USER_GROUP_MAP;
GROUP_ID    USER_ID  
4            1
4            2
4            3

这是您的代码的结果 posted.You 应该覆盖实体 类 中的 hashcode 和 equals 方法,以避免 table 中的数据重复。

用于测试上述关系映射的代码。

@Override
public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
    User user = new User();
    user.setName("Damian");
    userRepository.save(user);

    user = new User();
    user.setName("Marta");
    userRepository.save(user);

    user = new User();
    user.setName("Natalia");
    userRepository.save(user);

    UGroup uGroup = new UGroup();
    uGroup.setName("Mieszkanie");
    uGroup = uGroupRepository.save(uGroup);

    user = userRepository.findById(1).get();
    user.addGroup(uGroup);
    user = userRepository.save(user);

    // unable to execute

    user = userRepository.findById(2).get();
    user.addGroup(uGroupRepository.findById(4).get());
    user = userRepository.save(user);


    // unable to execute 2

    uGroup = uGroupRepository.findById(4).get();
    uGroup.addUser(userRepository.findById(3).get());
    uGroup = uGroupRepository.save(uGroup);

}