[英]Hibernate: Deleting in One-to-Many/Many-To-One fails
假設我們有三個實體: Course
, Student
和Guide
。 許多學生可以訪問許多課程,許多課程可以包含許多學生。這就是為什么我創建了Student
與Course
之間的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之間的Course
和Guide
與在側面的所有權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.REMOVE
, Java
課程也消失了:
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.