Подтвердить что ты не робот

Имейте 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, чтобы увидеть причину.

Я что-то делаю неправильно? Это что-то достижимо?

Спасибо.

4b9b3361

Ответ 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.