Які типи Cascade існують
JPA надає кілька типів каскадних операцій, кожен з яких контролює поширення конкретного типу операції на пов'язані сутності. Правильний вибір типу cascade — ключ до коректної ро...
Огляд
JPA надає кілька типів каскадних операцій, кожен з яких контролює поширення конкретного типу операції на пов’язані сутності. Правильний вибір типу cascade — ключ до коректної роботи з графами об’єктів.
🟢 Junior Level
Всі типи CascadeType
CascadeType.ALL — всі операції (persist, merge, remove, refresh, detach)
CascadeType.PERSIST — при persist(parent) → persist(child)
CascadeType.MERGE — при merge(parent) → merge(child)
CascadeType.REMOVE — при remove(parent) → remove(child)
CascadeType.REFRESH — при refresh(parent) → refresh(child)
CascadeType.DETACH — при detach(parent) → detach(child)
Приклад кожного
// PERSIST — збереження з children
@OneToMany(cascade = CascadeType.PERSIST)
private List<OrderItem> items;
entityManager.persist(order); // → persist для всіх items
// MERGE — оновлення з children
@OneToMany(cascade = CascadeType.MERGE)
private List<OrderItem> items;
entityManager.merge(order); // → merge для всіх items
// REMOVE — видалення з children
@OneToMany(cascade = CascadeType.REMOVE)
private List<OrderItem> items;
entityManager.remove(order); // → remove для всіх items
// ALL — всі операції
@OneToMany(cascade = CascadeType.ALL)
private List<OrderItem> items;
Коли НЕ використовувати cascade взагалі
Не використовуйте cascade коли обидві сутності — aggregate roots з власним життєвим циклом. Наприклад, Order та Customer — це окремі агрегати, каскад між ними небезпечний.
🟡 Middle Level
Коли що використовувати
@OneToMany (composite): CascadeType.ALL + orphanRemoval = true
@ManyToOne: CascadeType.PERSIST, MERGE (або без cascade)
@OneToOne: CascadeType.ALL
@ManyToMany: CascadeType.PERSIST, MERGE
Composite vs Association
// Composite — child не існує без parent
@Entity
public class Order {
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items; // OrderItem без Order не має сенсу
}
// Association — entities незалежні
@Entity
public class Order {
@ManyToOne // no cascade
private User user; // User існує незалежно від Order
}
Типові помилки
// ❌ Cascade.REMOVE для shared entities
@ManyToOne(cascade = CascadeType.REMOVE)
private User user;
entityManager.remove(order); // ❌ User теж видалено!
// ❌ Cascade.ALL для @ManyToOne
@ManyToOne(cascade = CascadeType.ALL)
private Category category;
entityManager.remove(product); // ❌ Category видалена!
// ✅ Без cascade для shared
@ManyToOne
private User user; // User управляється окремо
🔴 Senior Level
Матриця рішень
| Зв’язок | Cascade | orphanRemoval | Чому |
|---|---|---|---|
| @OneToMany (composite) | ALL | true | Child не існує без parent |
| @ManyToOne (shared) | PERSIST, MERGE | false | Entity управляється окремо |
| @OneToOne (composite) | ALL | true | Один до одного, композиція |
| @ManyToMany | PERSIST, MERGE | false | Shared entities, небезпечно видаляти |
Best Practices
✅ ALL для composite children
✅ PERSIST, MERGE для shared entities
✅ Без REMOVE для shared entities
✅ orphanRemoval для composite children
✅ Матриця рішень для кожного зв'язку
❌ REMOVE для shared entities
❌ ALL для @ManyToOne
❌ Cascade.REMOVE в Many-to-Many
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- 6 типів CascadeType: ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH
- ALL — всі операції, але небезпечний для @ManyToOne та Many-to-Many
- Композиції (Order → OrderItem): CascadeType.ALL + orphanRemoval = true
- Асоціації (Order → User): PERSIST, MERGE або без cascade
Пов’язані теми:
- [[20. Як працюють каскадні операції (Cascade)]]
- [[22. Що таке orphan removal]]
- [[23. Як правильно використовувати @OneToMany і @ManyToOne]]
- [[24. У чому особливості bidirectional relationships]]