JPA通过移除孤儿来维护OneToMany <-> ManyToOne <-> OneToMany关系

时间:2019-11-25 14:56:38

标签: spring-data-jpa

假设我们有以下表格

-------------------
| students        |
-------------------
| id              |
| ...             |
-------------------

-------------------
| student_course  |
-------------------
| student_id      |
| course_id       |
| ...             |
-------------------

-------------------
| courses         |
-------------------
| id              |
| ...             |
-------------------

从本质上讲,学生与课程之间存在多对多的关系。我不必使用@ManyToMany@JoinTable来将联接表映射为一个实体本身,而是使用student_id和course_id作为组合主键。连接表中还需要维护一些其他审核数据。

我已经尝试过像这样映射这种关系。

学生

@Entity
@Table(name = "students")
public class Student implements Serializable {

    // Id and other fields

    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<StudentCourse> studentCourses = new ArrayList<>();

    public void removeAllAssignedCourses() {
        for (int i=0; i < studentCourses.size(); i++) {
            removeAssignedCourse(studentCourses.get(i));
            i--;
        }
    }

    public void addAssignedCourse(Course course) {
      if (studentCourses.contains(studentCourse))
          return;
      StudentCourse studentCourse = new StudentCourse(this, course);
      studentCourses.add(studentCourse);
      course.getStudentCourses().add(studentCourse);
    }

    public void removeAssignedCourse(Course course) {
        Iterator<StudentCourse> iterator = studentCourses.iterator();

        while (iterator.hasNext()) {
            StudentCourse studentCourse = iterator.next();

            if (studentCourse.getStudent().equals(this) && studentCourse.getCourse().equals(course)) {
                iterator.remove();
                course.getStudentCourses().remove(studentCourse);
                studentCourse.setStudent(null);
                studentCourse.setCourse(null);
            }
        }
    }

    //getters setters equals and hashcode

}

课程

@Entity
@Table(name = "courses")
public class Course implements Serializable {

    // Id and other fields

    @OneToMany(mappedBy = "course", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<StudentCourse> studentCourses = new ArrayList<>();

    //getters setters equals and hashcode

}

要映射student_course表,我需要以下内容

StudentCourseId

@Embeddable
public class StudentCourseId implements Serializable {

    @Column(name = "student_id")
    private UUID studentId;

    @Column(name = "student_id")
    private UUID courseId;

    //getters and setters and equals and hashcode

}

学生课程

@Entity
@Table(name = "student_course")
public class StudentCourse implements Serializable {

    @EmbeddedId
    private StudentCourseId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("STUDENT_ID")
    @JoinColumn(name = "STUDENT_ID")
    private Student student;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("COURSE_ID")
    @JoinColumn(name = "COURSE_ID")
    private Course course;

    public StudentCourse(Student student, Course course) {
        this.student = student;
        this.course = course;
        this.id = new StudentCourseId(student.getId(), course.getId());
    }

    // getters, setters, equals and hashcode

}

添加关系时,这似乎很好,我可以很高兴地创建一个新学生,然后保持他/她的学生/课程关系

Course course = new Course("math");
course = courseRepository.save(course);
Student student = new Student("paul");
student = studentRepository.save(student);
student.addAssignedCourse(math);
student = studentRepository.save(student);

但是,如果我希望这样,那就从学生那儿删除所有课程并分配一些新课程

student.removeAllAssignedCourses();
student = studentRepository.save(student);

我收到类似于以下内容的异常

  

由以下原因引起:org.hibernate.HibernateException:请勿更改   引用启用了delete-orphan的集合:   com.example.Student.student课程

这似乎是由于我的removeAssignedCourse方法中的以下原因

course.getStudentCourses().remove(studentCourse);

但是,对此进行注释会导致进一步的问题,因为该课程仍然引用了StudentCourse。维持这种关系的最佳方法是什么?

0 个答案:

没有答案