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 отправятся в базу данных, и произойдет следующее:
- Hibernate заметит, что у объекта Customer уже не 4, а 3 связанных дочерних объекта Order;
- в связи с этим Hibernate найдёт в таблице Order строку с удаленным объектом из коллекции Order;
- очистит в этой строке ячейку с внешним ключом на Customer;
- после чего удалит саму эту строку, как осиротевшую (более не ссылающуюся на родителя).
Если не будет атрибута orphanRemoval = true, то пункт 4 не выполнится, и в таблице Order останется сущность Order, не связанная ни с одной сущностью Customer, то есть её ячейка с внешним ключом будет пустой. Такая сущность будет считаться осиротевшей.
Предыдущий вопрос: 13.Что такое владелец связи?
Следующий вопрос: 15. Какие два типа fetch-стратегии в JPA вы знаете?
Все вопросы по теме: список
Все темы: список
Вопросы/замечания/предложения/нашли ошибку: напишите мне