簡體   English   中英

休眠狀態:一對多/多對一刪除失敗

[英]Hibernate: Deleting in One-to-Many/Many-To-One fails

假設我們有三個實體: CourseStudentGuide 許多學生可以訪問許多課程,許多課程可以包含許多學生。這就是為什么我創建了StudentCourse之間的bidirectional Many-To-Many多對多關系:

@Entity()
@Getter
@Setter
@ToString(exclude = "courses")
@Builder
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @ManyToMany(cascade = CascadeType.REMOVE)
    @JoinTable(
            name = "courses_students",
            joinColumns = @JoinColumn(name = "students_id"),
            inverseJoinColumns = @JoinColumn(name = "courses_id"))
    private Set<Course> courses;


}

@Entity
@Builder
@Getter
@Setter
@ToString(exclude = "guide")
@Table(name="courses")
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne()
    @JoinColumn(name="guide_id")
    private Guide guide;

    @Column
    private String title;

    @ManyToMany(mappedBy = "courses")
    Set<Student> students;
}

此外,每門課程只有一個指南,但是一個指南可以教授多門課程。 因此,有一個birectional One-to-Many / Many-to-One -Relationship之間的CourseGuide與在側面的所有權Course

@Entity
@Table(name = "guides")
@Getter
@Setter
@Builder
public class Guide {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @OneToMany(mappedBy = "guide")
    private List<Course> courses = new ArrayList<>();

}

當我通過Cascade.Remove刪除所有學生時,所有Course實體也將被刪除,這很好。 但是,當我從GuideRepository檢索Guide GuideRepository並調用<guideInstance>.getCourses()時,我得到的是課程列表。 我希望有一個空列表,因為從CourseRepository我什么也收不到! 這是什么問題?

為了重現該問題,我發布了用於創建實體的代碼:

 Course java= Course.builder().title("Java").build();
    Course python= Course.builder().title("Python").build();
    Course kotlin= Course.builder().title("Kotlin").build();

    Set<Course> johnCourses=new HashSet<>();
    johnCourses.add(java);
    johnCourses.add(python);

    Set<Course> jackCourses=new HashSet<>();
    jackCourses.add(java);
    jackCourses.add(python);
    jackCourses.add(kotlin);

    Set<Course> henryCourses=new HashSet<>();
    henryCourses.add(python);
    henryCourses.add(kotlin);

    List<Course> drMorrisCourses=new ArrayList<Course>();
    drMorrisCourses.add(java);
    drMorrisCourses.add(kotlin);

    List<Course> drFerrisCourses=new ArrayList<Course>();
    drFerrisCourses.add(python);

    Guide drMorris = Guide.builder().name("Dr. Morris").courses(drMorrisCourses).build();
    Guide drFerris = Guide.builder().name("Dr. Ferris").courses(drFerrisCourses).build();

    Student john= Student.builder().name("John").courses(johnCourses).build();
    Student jack= Student.builder().name("Jack").courses(jackCourses).build();
    Student henry= Student.builder().name("Henry").courses(henryCourses).build();

    Set<Student> javaStudents=new HashSet<>();
    javaStudents.add(john);
    javaStudents.add(jack);

    Set<Student> kotlinStudents=new HashSet<>();
    kotlinStudents.add(jack);
    kotlinStudents.add(henry);

    Set<Student> pythonStudents=new HashSet<>();
    pythonStudents.add(john);
    pythonStudents.add(henry);
    pythonStudents.add(jack);

    java.setGuide(drMorris);
    kotlin.setGuide(drMorris);
    python.setGuide(drFerris);

    java.setStudents(javaStudents);
    python.setStudents(pythonStudents);
    kotlin.setStudents(kotlinStudents);

    studentRepository.save(john);
    studentRepository.save(jack);
    studentRepository.save(henry);

    courseRepository.save(java);
    courseRepository.save(kotlin);
    courseRepository.save(python);

    guideRepository.save(drMorris);
    guideRepository.save(drFerris);

現在所有實體都已設置。 要刪除一個學生,我可以使用例如以下代碼:

      List<Student> allStudents = studentRepository.findAll();
//Here I choose for example first student and delete it!        
studentrepository.delete(allStudents.get(0));

我刪除了第一個Student -Entity,即John ,它訪問Java課程。 隨着John的刪除,由於Cascase.REMOVEJava課程也消失了:

List<Course> courses =courseRepository.findAll();
courses.size() // -> only 2 because Java course entity is deleted!!!!

但是,如果我調用第一個向導實體,那意味着drMorris我可以看到drMorris仍然具有Java課程,盡管Java課程實體被刪除了:

List<Guide> guides=guideRepository.findAll();
guides.get(0).getCourses //<- drMorris should not have Java Course!!!!!!!!

這是我的解決方案:

   public void deleteStudents(){
        List<Student> all = studentRepository.findAll();
       deleteStudent(all.get(2));
     }

     public void deleteStudent(Student student) {

        Set<Course> courses = student.getCourses();

         for (Course course: courses) {
             if (course.getStudents().size() == 1 ){
                 course.getGuide().getCourses().remove(course);

                 courseRepository.delete(course);
             } else {
                 course.getStudents().remove(student);
             }
         }
         studentRepository.delete(student);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM