Имейте JPA/Hibernate, чтобы воспроизвести функциональность "ON DELETE SET NULL"
Я смог иметь JPA/Hibernate для успешной репликации функциональных возможностей ON DELETE CASCADE
(похоже на поведение по умолчанию), но теперь я пытаюсь реплицировать функциональность ON DELETE SET NULL
, и мне приходится сталкиваться с проблемами.
Это мои два класса:
@Entity
@Table(name = "teacher")
public class Teacher
{
@Id
@GeneratedValue
@Column(name = "id", nullable = false, length = 4)
private int id;
@OneToMany(mappedBy = "teacher")
private List<Student> studentList;
// ...
}
@Entity
@Table(name = "student")
public class Student
{
@Id
@GeneratedValue
@Column(name = "id", nullable = false, length = 4)
private int id;
@ManyToOne(optional = true)
@JoinColumn(name = "teacher_id", nullable = true)
private Teacher teacher;
// ...
}
Когда я пытаюсь удалить учителя, появляется следующая ошибка:
org.springframework.dao.DataIntegrityViolationException: Не удалось выполнить пакетное обновление JDBC; SQL [удалить из учителя, где teacher_id =?]; ограничение [null]
...
Вызвано: org.hibernate.exception.ConstraintViolationException: не удалось выполнить пакетное обновление JDBC
...
Вызывается: java.sql.BatchUpdateException: Пакетный ввод 0 удаляется из учителя, где teacher_id = '1' был прерван. Вызовите getNextException, чтобы увидеть причину.
Я что-то делаю неправильно? Это что-то достижимо?
Спасибо.
Ответы
Ответ 1
В настоящий момент это не представляется возможным с jpa/hibernate.
В поле delete set null в спящем режиме в @OneToMany
Решение JBs кажется чистым, хотя:
for (Department child : parent.getChildren()) {
child.setParentDepartment(null);
}
session.delete(parent);
Вы также можете установить его в PreRemove:
@PreRemove
private void preRemove() {
for (Student s : studentList) {
s.setTeacher(null);
}
}
Ответ 2
Как насчет определения
@ForeignKey(name = "fk_student_teacher",
foreignKeyDefinition = " /*FOREIGN KEY in sql that sets ON DELETE SET NULL*/")
?
Ответ 3
Я думаю, что лучшее решение - это оператор SQL для установки действия удаления следующим образом:
CREATE TABLE table_name
(
column1 datatype null/not null,
column2 datatype null/not null,
...
CONSTRAINT fk_column
FOREIGN KEY (column1, column2, ... column_n)
REFERENCES parent_table (column1, column2, ... column_n)
ON DELETE SET NULL
);
когда пользователь удаляет строку другим каскадным удалением, когда вы используете ссылку на таблицу на эту удаленную строку, вы не можете использовать решение гибернации и возвращать исключение SQL.