Ошибка удаления экземпляра объекта с отношением MANY_TO_MANY без каскадирования - PullRequest
0 голосов
/ 19 сентября 2011

У меня есть два класса (Студенты и Курсы), которые имеют отношения многие ко многим. Их экземпляры могут существовать без другого. Поэтому я удалил каскадный атрибут в JPA-аннотации: @ManyToMany (cascade = CascadeType.ALL)

Как только я пытаюсь удалить Студента, я получаю это сообщение об ошибке.

Что я делаю не так?

org.hibernate.exception.ConstraintViolationException: не удалось удалить: [com.Student # 4]; вложенное исключение javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: не удалось удалить: [com.Student # 4]

Это вывод Hibernate:

Hibernate: удалить из ученика, где id =? а версия =? 2011-09-19 15: 25: 10,317 [http-8080-3] ОШИБКА org.hibernate.util.JDBCExceptionReporter - Невозможно удалить или обновить родительская строка: ограничение внешнего ключа не выполнено (database. student_course, ОГРАНИЧЕНИЕ FKF8A06F72970A31AF ИНОСТРАННЫЙ КЛЮЧ (students) ССЫЛКИ students (id))

Это соответствующие части обоих классов:

@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>();
}

1 Ответ

1 голос
/ 22 сентября 2011

Я собирался предложить добавить detachFromCourses() метод к вашему Student, который перебирает courses, удаляя this.Вы бы назвали это как раз перед удалением Student.Но это уродливо и не очень хорошо подходит для Spring Roo.

Могу ли я предложить создать JPA Entity Listener , подключенный к событию @PreRemove JPA?Тогда вы можете сохранить свою модель домена и ваши контроллеры свободными от специфичных для базы данных вещей.Ваш прослушиватель сущностей может просто сделать:

@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);
        }
    }
}
...