I've got two classes (Students and Courses) which have a many-to-many-relationship. Instances of them can exist without the other one. Therefore I removed the cascade-attribute in the JPA-annotation: @ManyToMany(cascade = CascadeType.ALL)
Once I try to delete a Student I get this error-message.
What am I doing wrong?
org.hibernate.exception.ConstraintViolationException: could not delete: [com.Stude开发者_开发百科nt#4]; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not delete: [com.Student#4]
This is the Hibernate-output:
Hibernate: delete from student where id=? and version=? 2011-09-19 15:25:10,317 [http-8080-3] ERROR org.hibernate.util.JDBCExceptionReporter - Cannot delete or update a parent row: a foreign key constraint fails (
database
.student_course
, CONSTRAINTFKF8A06F72970A31AF
FOREIGN KEY (students
) REFERENCESstudents
(id
))
These are the relevant parts of both classes:
@RooJavaBean
@RooToString
@RooEntity
public class Student{
@ManyToMany
private Set<Course> courses= new HashSet<Course>();
}
@RooJavaBean
@RooToString
@RooEntity
public class Course {
@ManyToMany(mappedBy = "courses")
private Set<Student> students= new HashSet<Student>();
}
I was going to suggest adding a detachFromCourses()
method to your Student
, which iterates over the courses
, removing this
. You'd call that just before deleting a Student
. But that's ugly and it doesn't fit very well with Spring Roo.
May I suggest looking into creating a JPA Entity Listener hooked up to the @PreRemove
JPA event? Then you can keep your domain model and your controllers free of database-specific stuff. Your Entity Listener could then just do:
@PreRemove
void onPreRemove(Object o) {
if (o instanceof Student) {
// Remove all the course references to this Student
Student s = (Student) o;
for (Course c : s.getCourses()) {
c.getStudents().remove(s);
}
}
}
精彩评论