开发者

Deleting an instance of an object with a MANY_TO_MANY relationship without cascading fails

开发者 https://www.devze.com 2023-04-06 09:28 出处:网络
I\'ve got two classes (Students and Courses) which have a many-to-many-relationship. Instances of them can exist without the other one.

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, CONSTRAINT FKF8A06F72970A31AF FOREIGN KEY (students) REFERENCES students (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);
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消