Hibernate сохраняет дубликаты для отношений ManyToMany - PullRequest
0 голосов
/ 14 июля 2020

В моем тестовом классе Spring я пытаюсь заполнить свою базу данных методом @BeforeAll.

@BeforeAll
static void beforeAll(@Autowired TeamRepository teamRepository,
                      @Autowired StudentRepository studentRepository) {

    teams = new ArrayList<>();
    students = new ArrayList<>();

    final int nTeams = 20;

    IntStream.range(0, nTeams)
            .forEach(i -> {

                Team team = Team.builder()
                        .name("team-"+i)
                        .status(TeamStatus.ACTIVE)
                        .members(new ArrayList<>())
                        .build();
                teams.add(team);

                teamRepository.save(team);

                IntStream.range(0, 3)
                        .forEach(k -> {

                            Student student = Student.builder()
                                    .id("s" + k + "-" + i)
                                    .name("name-" + k + "-" + i)
                                    .firstName("first_name-" + k + "-" + i)
                                    .teams(new ArrayList<>())
                                    .build();
                            team.addStudent(student);
                            students.add(student);

                            studentRepository.save(student);
                        });

            });

}

Связь между двумя объектами - @ ManyToMany.

Student.java

@Entity
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Student {

    @Id
    @EqualsAndHashCode.Include
    String id;
    String name;
    String firstName;

    @ManyToMany(mappedBy = "members", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    List<Team> teams = new ArrayList<>();

    public void addTeam(Team team) {
        teams.add(team);
        team.members.add(this);
    }

    public void removeTeam(Team team) {
        teams.remove(team);
        team.members.remove(this);
    }
}

Team.java

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Team {
    @Id
    @GeneratedValue
    @EqualsAndHashCode.Include
    Long id;
    String name;
    TeamStatus status;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "team_student",
            joinColumns = @JoinColumn(name = "team_id"),
            inverseJoinColumns = @JoinColumn(name = "student_id")
    )
    List<Student> members = new ArrayList<>();

    public void addStudent(Student student) {
        members.add(student);
        student.teams.add(this);
    }

    public void removeStudent(Student student) {
        members.remove(student);
        student.teams.remove(this);
    }
}

С этим кодом Hibernate будет сохранять дубликаты, как показано на изображениях ниже. Единственное решение, которое я нашел, - не вызывать studentRepository.save() и сохранять team только в конце. Причина, по которой я публикую этот вопрос, заключается в том, что я пытаюсь понять, почему это происходит и почему количество дубликатов различается для разных объектов.

Пример:

enter image description here

enter image description here

введите описание изображения здесь

...