Hibernate @ManyToOne удалить запись на одной стороне, установите FK в NULL на многие стороны - PullRequest
2 голосов
/ 06 июля 2011

Я пытаюсь научиться работать с Hibernate, но, вероятно, я не понимаю @ManyToOne и обратные отношения.У меня есть две сущности Author и Department.Один автор имеет один отдел, один отдел имеет много авторов.

Когда я удаляю автора, с отделом ничего не должно происходить.Когда я удаляю Отдел, FK в таблице Автора должен быть обновлен до значения NULL (Автор НЕ должен быть удален).

Я нашел хорошее объяснение инверсии и выяснил, что Author является владельцем, и в соответствии с этой веткой при удалении дочернего элемента (Отдела) FK должен быть установлен на NULL.Но этого не происходит, потому что удаляется только Department и FK остается в таблице Author (что приводит к org.hibernate.ObjectNotFoundException: No row with the given identifier exists).

Когда я добавляю аннотацию CascadeType.REMOVE к @OneToMany в сущности Department, тогда всеПривязанные к отделу авторы также удаляются.Ни одно из вышеупомянутых состояний не желательно.Я просто хочу удалить Отдел и установить FK в таблице Автор на NULL.Как это сделать?

Author и Department сущностей с аннотациями:

@Entity
@Table(name = "author")
public class Author implements Serializable {

    @Id
    @Column(name = "idauthor")
    @GeneratedValue
    private Integer idAuthor;

    @DepartmentFormat
    @ManyToOne
    @JoinColumn(name = "department", nullable = true)
    private Department department;
}

@Entity
@Table(name="department")
public class Department implements Serializable {

    @Id
    @Column(name="iddepartment")
    @GeneratedValue
    private Integer iddepartment;

    @OneToMany(mappedBy = "department", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    private Set<Author> authors;
}

Заранее спасибо

1 Ответ

2 голосов
/ 06 июля 2011

Не существует автоматического способа установки всех внешних ключей на null при удалении какого-либо объекта.Вы должны явно получить всех авторов отдела, установить для их отдела значение NULL, а затем удалить отдел.

Для этого также можно использовать запрос массового обновления:

update Author a set a.department = null where a.department = :department

(и, следовательно, иметь только один запрос вместо n + 1), но имейте в виду, что поле версии не будет обновлено, что не будет никакой оптимистической проверки блокировки, и что уже загруженные отделы сеанса выиграли 'Это не повлияет (в памяти), если вы это сделаете.

Обратите внимание, что у вас не должно быть исключения ObjectNotFoundException при удалении сущности, на которую ссылается другая.Вместо этого вы должны включить ограничение внешнего ключа в базе данных, чтобы удаление отдела завершилось неудачно, если на него все еще ссылается автор.Таким образом, ваши данные остаются в согласованном состоянии.

...