Java 休眠:一对多/多对一删除失败

Java 休眠:一对多/多对一删除失败,java,hibernate,jpa,spring-data-jpa,one-to-many,Java,Hibernate,Jpa,Spring Data Jpa,One To Many,假设我们有三个实体:课程,学生和指南。 许多学生可以访问许多课程,许多课程可以包含许多学生。这就是为什么我在学生和课程之间创建了一个双向多对多-关系: @Entity() @Getter @Setter @ToString(exclude = "courses") @Builder @Table(name = "students") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDEN

假设我们有三个实体:
课程
学生
指南
。 许多学生可以访问许多课程,许多课程可以包含许多学生。这就是为什么我在
学生
课程
之间创建了一个
双向多对多
-关系:

@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
@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
all
Course
-实体也会被删除,这很好。但是,当我从
指南存储库
检索
指南
实例并调用
.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);
但是如果我调用第一个向导实体,这意味着
drMorris
我可以看到
drMorris
仍然有
Java
课程,尽管
Java
课程实体被删除了!:

List<Guide> guides=guideRepository.findAll();
guides.get(0).getCourses //<- drMorris should not have Java Course!!!!!!!!
List guides=guideRepository.findAll();
guides.get(0).getCourses/以下是我的解决方案:

   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);
    }
public void deleteestudents(){
List all=studentRepository.findAll();
删除学生(全部获得(2));
}
公立学校学生(学生){
设置课程=student.getCourses();
用于(课程:课程){
if(course.getStudents().size()=1){
course.getGuide().getCourses().remove(课程);
courseRepository.delete(课程);
}否则{
course.getStudents().remove(student);
}
}
studentRepository.delete(学生);
}
以下是我的解决方案:

   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);
    }
public void deleteestudents(){
List all=studentRepository.findAll();
删除学生(全部获得(2));
}
公立学校学生(学生){
设置课程=student.getCourses();
用于(课程:课程){
if(course.getStudents().size()=1){
course.getGuide().getCourses().remove(课程);
courseRepository.delete(课程);
}否则{
course.getStudents().remove(student);
}
}
studentRepository.delete(学生);
}

我们不知道,因为您没有发布重现问题的代码。但是在多个XXX关联上使用cascade=REMOVE总是一个坏主意。如果我删除了学生John,那么John访问的所有课程都不应该被删除:Jane、Jack和Henry也访问了该课程,因此,如果您的数据库中有正确的外键约束,那肯定会失败,但有一个例外。但是您的代码没有显示您如何删除该学生?我们不知道,因为你没有发布重现问题的代码。但是在多个XXX关联上使用cascade=REMOVE总是一个坏主意。如果我删除了学生John,那么John访问的所有课程都不应该被删除:Jane、Jack和Henry也访问了该课程,因此如果您的数据库中有正确的外键约束,那么肯定会出现异常而失败。但是您的代码没有显示如何删除该学生?
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);
    }