Please look at the following code snippets from 2 classes (Entities) Student
and Course
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;
...
}
and the driver code is as follows
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();
}
When I run this code I am getting the following exception
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
So my doubt is. persisting the Course does not persist the associated Student(s) even though we have mentioned CascadeType.ALL in the Course class. So why the cascading is not working in the case of many to many?
nb: When I saved both the student objects using session.save()
, before saving the course object. There were no exception.
@JoinTable
annotation only on the owning side of the @ManyToMany
association.@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;
// ...
}
Course
entity: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 );
}
// ...
}
and then you will be able to do something like 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);
For
@ManyToMany
associations, theREMOVE
entity state transition doesn't make sense to be cascaded because it will propagate beyond the link table. Since the other side might be referenced by other entities on the parent-side, the automatic removal might end up in aConstraintViolationException
.
That is why you should avoid to use cascade = CascadeType.ALL
in the @ManyToMany
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.