14. Что такое каскадные операции?

14. Что такое каскадные операции?

UNKNOWN

Каскадные операции и отношения

Сущности, между которыми есть отношения, часто зависят от существования друг друга. Например, позиции (LineItem) являются частью заказа (CustomerOrder), и если  заказ  удален,  все  позиции  также  должны  быть  удалены.  Это  называется каскадным удалением.

JPA позволяет распространять операции с сущностями (например, persist или remove) на связанные сущности. Это означает, что при включенном каскадировании, если  сущность  A  сохраняется  или  удаляется,  тогда  сущность  B  (связанная  с  A отношением, например через ManyToOne) также будет сохраняться или удаляться без явных команд сохранения или удаления.

Каскадирования  можно  добиться,  указав  у  любой  из  аннотаций  @OneToOne, @ManyToOne, @OneToMany, @ManyToMany элемент cascade и присвоив ему одно или несколько значений из перечисления CascadeType (ALL, DETACH, MERGE, PERSIST, REFRESH, REMOVE).

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

Удаление сирот в отношениях (Orphan Removal)

Представим, что у нас есть класс Customer, у которого есть коллекция Order:

@Entity

public class Customer {

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)

    private List<Order> orders = new ArrayList<>();

    // other mappings, getters and setters

}

Пусть у нас есть один объект Customer - родитель, в коллекции которого есть 4 объекта  Order  -  дети,  и  мы  установили  атрибут  orphanRemoval  =  true  над  этой коллекцией. В нашей базе данных в таблице Customer будет одна строка, а в таблице Order будет четыре строки. Также в таблице Order будет колонка с внешними ключами на таблицу Customer. В каждой из четырех ячеек этой колонки будут ссылки на один и тот же первичный ключ объекта Customer.

Например, мы удалим из коллекции orders один объект Order - любой из четырех, в результате чего у объекта Customer останется три объекта Order:

Customer customer = entityManager.find(Customer.class, 1L);

Order order = customer.getOrders().get(0);

customer.getOrders().remove(order);

flushAndClear(); 

После запуска метода flushAndClear() - обновления объекта Customer отправятся в базу данных, и произойдет следующее:

  1. Hibernate заметит, что у объекта Customer уже не 4, а 3 связанных дочерних объекта Order;
  2. в связи с этим Hibernate найдёт в таблице Order строку с удаленным объектом из коллекции Order;
  3. очистит в этой строке ячейку с внешним ключом на Customer;
  4. после чего удалит саму эту строку, как осиротевшую (более не ссылающуюся на родителя).

Если не будет атрибута orphanRemoval = true, то пункт 4 не выполнится, и в таблице  Order  останется  сущность  Order,  не  связанная  ни  с  одной  сущностью Customer, то есть её ячейка с внешним ключом будет пустой. Такая сущность будет считаться осиротевшей.


Предыдущий вопрос: 13.Что такое владелец связи?

Следующий вопрос: 15. Какие два типа fetch-стратегии в JPA вы знаете?

Все вопросы по теме: список

Все темы: список

Вопросы/замечания/предложения/нашли ошибку: напишите мне

Report Page