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
allCourse
-实体也会被删除,这很好。但是,当我从指南存储库
检索指南
实例并调用.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);
}