繁体   English   中英

为什么级联持久化在 Hibernate 中不适用于多对多关系?

[英]Why the Cascading persist does not work with many-to-many relationship in Hibernate?

请查看以下 2 个类(实体) StudentCourse代码片段

public class Student {
   ...

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name = "course_student",
        joinColumns = @JoinColumn(name="student_id"),
        inverseJoinColumns = @JoinColumn(name="course_id")
   )
   private List<Course> courses;
   
   ...
}
    
public class Course {
   ...
   
   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name = "course_student",
        joinColumns = @JoinColumn(name="course_id"),
        inverseJoinColumns = @JoinColumn(name="student_id")
   )
   private List<Student> students;
   
   ...
}

驱动代码如下

try {
    session.beginTransaction();
    Course course = new Course("Ukulele master class");
    Student student1 = new Student("Jishnu","M V","jishnumv@gmail.com");
    Student student2 = new Student("Praveen","M V","praveenmv@gmail.com");
    course.add(student1);
    course.add(student2);
    session.save(course);
    session.getTransaction().commit();
} 

当我运行此代码时,出现以下异常

Exception in thread "main" java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.jithin.entity.Student

所以我的怀疑是。 即使我们在 Course 类中提到了 CascadeType.ALL,持久化课程也不会持久化关联的学生。 那么为什么级联在多对多的情况下不起作用呢?

注意:当我使用session.save()保存两个学生对象时,在保存课程对象之前。 没有例外。

  1. 您应该只在@ManyToMany关联的拥有方使用@JoinTable注释。
@Entity
public class Student {

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "course_student",
            joinColumns = @JoinColumn(name="student_id"),
            inverseJoinColumns = @JoinColumn(name="course_id"))
    private List<Course> courses;
   
   // ...
}

@Entity
public class Course {

    @ManyToMany(mappedBy = "courses", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private List<Student> students;

   // ...
}
  1. 如果您使用双向关联,您应该注意关联双方的同步。 因此,您应该将以下方法添加到Course实体中:
public class Course {

  public void addStudent(Student student) {
     students.add(student);
     student.getCourses().add( this );
  }

  public void removeStudent(Student student) {
     students.remove(student);
     student.getCourses().remove( this );
  }

  // ...
}

然后你将能够做这样的事情:

Course course = new Course("Ukulele master class");
Student student1 = new Student("Jishnu","M V","jishnumv@gmail.com");
Student student2 = new Student("Praveen","M V","praveenmv@gmail.com");
course.addStudent(student1);
course.addStudent(student2);
session.save(course);
  1. 正如它在文档中提到的:

对于@ManyToMany关联, REMOVE实体状态转换对于级联没有意义,因为它会传播到链接表之外。 由于另一端可能被父端的其他实体引用,因此自动删除可能以ConstraintViolationException结束。

这就是为什么你应该避免在@ManyToMany使用cascade = CascadeType.ALL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM