Найти тему
Степан Скворцов

Как удалить дочерние записи в отношениях OneToMany из базы данных в JPA?

Когда мы моделируем базу данных, мы, скорее всего, определяем несколько ассоциаций "многие-к-одному" или "один-ко-многим". И, конечно же, то же самое происходит, когда мы моделируем сущности.

Это довольно просто сделать с помощью JPA и Hibernate. Вам просто нужен атрибут, который представляет ассоциацию и аннотирует ее с @ManyToOne или @OneToMany ассоциацией.

Но как бы легко это ни казалось, здесь, к сожалению, есть несколько подводных камней.

Давайте смоделируем сущности Vendor и Client и создадим между ними двунаправленную связь One to Many.

Итак, мы создаем поставщика и клиента, сохраняем их в БД, затем получаем клиента из БД, удаляем его и, наконец, убеждаемся, что все работает, как ожидалось.

Но это не так.

Это происходит потому, что JPA на самом деле не знает, следует ли ему удалять что-то удаленное из коллекции. Но подождите. Тогда как мы удалим дочернюю сущность из базы данных?

Hibernate делает это автоматически, когда вы устанавливаете атрибут orphanRemoval аннотации @OneToMany в true и атрибут cascade в CascadeType.ALL, он автоматически удаляет дочерние сущности при удалении родительской.

CascadeType.ALL означает, что все переходы состояния сущностей JPA и Hibernate (например, persist, merge, remove) передаются от родительской сущности Vendor к дочерним сущностям Client.

Атрибут orphanRemoval будет указывать провайдеру JPA инициировать переход состояния удаления сущности, когда на сущность Client больше не ссылается ее родительская сущность Vendor.

Поскольку у нас двунаправленная ассоциация "один ко многим", нам необходимо убедиться, что обе стороны ассоциации синхронизированы, и по этой причине мы создали методы addClient и removeClient для синхронизации обеих сторон при добавлении или удалении новой клиентской сущности.

Заключение

Вот и все с моей стороны. Надеюсь, вы узнали что-то новое из этой статьи. Я старался изо всех сил, чтобы все было как можно проще. Спасибо за прочтение.