14 · Hibernate and Spring Data JPA in depth / LESSON 67 OF 102
Cascade, orphan removal, and many-to-many design
Deletion propagation should follow aggregate ownership, not convenience.
Before this lesson: Many-to-one, one-to-many, and relationship ownership
Understand the topic
CascadeType.REMOVE can delete related entities; it is dangerous on shared references such as an owner or tag. orphanRemoval deletes a child removed from its owning aggregate relationship. Use it only where the child lifecycle genuinely belongs to the parent.
A many-to-many join table is sufficient for a pure association. When the relationship gains attributes such as assignedAt or role, model an explicit join entity. Shared tags should survive deleting one task.
EXAMPLE · JAVA
Aggregate mapping fragment
// In a Project entity whose Task children are exclusive to it.
@OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private java.util.List<Task> tasks = new java.util.ArrayList<>();
public void remove(Task task) {
tasks.remove(task);
task.setProject(null);
}What to expect
Requires Task.project plus its setter and consistent entity identity. Removing a managed child schedules orphan deletion at flush. Do not copy this lifecycle policy onto shared tags.
YOUR TURN
Put it into practice
- 01Model project-owned tasks and shared tags separately.
- 02Delete a project and then remove one task-tag association while inspecting affected rows.
- 03Verify: Owned children follow the chosen lifecycle while shared tags remain intact.
Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.
UNDER THE HOOD
Build the mental model
Deletion propagation should follow aggregate ownership, not convenience.
- 01CascadeType.REMOVE can delete related entities; it is dangerous on shared references such as an owner or tag. orphanRemoval deletes a child removed from its owning aggregate relationship. Use it only where the child lifecycle genuinely belongs to the parent.
- 02A many-to-many join table is sufficient for a pure association. When the relationship gains attributes such as assignedAt or role, model an explicit join entity. Shared tags should survive deleting one task.
- 03Trace the example: Requires Task.project plus its setter and consistent entity identity. Removing a managed child schedules orphan deletion at flush. Do not copy this lifecycle policy onto shared tags.
A mistake worth avoiding
Deleting one task unexpectedly deletes a shared category.
DEBUGGING ROOM
Something broke. Where do you look?
Deleting one task unexpectedly deletes a shared category.
Before revealing the diagnosis, write down your first investigation step.
CHECK YOUR UNDERSTANDING
Is cascade REMOVE safe by default on a shared many-to-many target?
BUILD IT YOURSELF
Model project-owned tasks and shared tags separately.
- 1.Model project-owned tasks and shared tags separately.
- 2.Delete a project and then remove one task-tag association while inspecting affected rows.
- 3.Reproduce this failure, then repair it: Deleting one task unexpectedly deletes a shared category.
Acceptance checklist
Lab completion is your self-report. Knowledge checks do not certify project quality.
RETRIEVE IT FROM MEMORY
Is cascade REMOVE safe by default on a shared many-to-many target?
Revisit this lesson in three days after a successful check or lab.
Ready for the next step?
Owned children follow the chosen lifecycle while shared tags remain intact.
Reading is separate from passing a knowledge check or completing a lab.