Definition
Both are HAS-A relationships but differ in lifecycle ownership.
- Aggregation (weak HAS-A): the child can exist independently of the parent. The parent has children but does not own their lifecycle. If the parent is destroyed, children survive. In JPA: no cascade delete.
- Composition (strong OWNS-A): the child cannot exist without the parent. The parent owns the child's lifecycle: creates, manages, and destroys it. If the parent is destroyed, children are also destroyed. In JPA:
cascade = ALL, orphanRemoval = true. - Decision rule: can the child exist meaningfully without the parent? If yes, aggregation. If no, composition.
Aggregation: a Branch of National Bank of India has Employees. If the branch is closed, employees do not disappear; they transfer to another branch. Employees existed before joining and exist after leaving. Composition: a Loan owns its EMIs. If the loan is closed, all its EMIs are deleted. An EMI without a loan is meaningless: which loan's installment?
Understanding the Concepts
What is aggregation vs composition?
The lifecycle is the key differentiator.
What does aggregation look like?
package com.bank.model;
import java.util.ArrayList;
import java.util.List;
public class Branch {
private String branchCode;
private List<Employee> employees = new ArrayList<>();
public void addEmployee(Employee emp) { employees.add(emp); }
public void removeEmployee(Employee emp) { employees.remove(emp); }
public List<Employee> close() {
List<Employee> surviving = new ArrayList<>(employees);
employees.clear();
return surviving; // employees survive branch closure
}
}
// Employee exists independently. Created outside Branch. Survives Branch deletion.
What does composition look like?
package com.bank.model;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class Loan {
private String loanId;
private BigDecimal principal;
private final List<EMI> emis = new ArrayList<>();
public Loan(String loanId, BigDecimal principal, int tenureMonths, BigDecimal rate) {
this.loanId = loanId;
this.principal = principal;
generateEMIs(tenureMonths, rate); // Loan creates EMIs
}
private void generateEMIs(int months, BigDecimal rate) {
BigDecimal emiAmount = calculateEMI(principal, rate, months);
for (int i = 1; i <= months; i++) {
emis.add(new EMI(loanId + "-EMI-" + i, i, emiAmount));
}
}
public void close() {
emis.clear(); // EMIs die with the loan
}
}
// EMI cannot exist alone. Created by Loan. Destroyed with Loan.
How do they compare?
| Aspect | Aggregation | Composition |
|--------|------------|-------------|
| Lifecycle | Independent | Bound to parent |
| Child survives parent? | Yes | No |
| Who creates child? | External | Parent |
| UML | Hollow diamond | Filled diamond |
| JPA | No cascade | cascade ALL + orphanRemoval |
| Example | Branch has Employees | Loan owns EMIs |
What does the JPA mapping look like?
// Aggregation: no cascade delete
@Entity
public class Branch {
@OneToMany // no cascade
private List<Employee> employees;
}
// Composition: cascade ALL + orphanRemoval
@Entity
public class Loan {
@OneToMany(mappedBy = "loan", cascade = javax.persistence.CascadeType.ALL, orphanRemoval = true)
private List<EMI> emis;
}
When do you use each?
Aggregation: child has independent lifecycle, can belong to multiple parents, created outside the parent. Composition: child has no meaning without parent, created by the parent, belongs to exactly one parent.
What are common mistakes?
The most common mistake is using aggregation when composition is correct, leaving orphan rows in the database.
What should a senior engineer know?
- In Domain-Driven Design, the Aggregate Root pattern is composition: the root entity owns all child entities.
- In microservices, composition maps to data owned by one service; aggregation maps to references across service boundaries.
Visual Overview
AGGREGATION (weak HAS-A) Branch ◇────→ Employee ┌─────────────┐ ┌──────────┐ │ Branch │───→│ Employee │ │ close() │ │ survives │ └─────────────┘ └──────────┘ Branch deleted → Employee lives on COMPOSITION (strong OWNS-A) Loan ◆────→ EMI ┌─────────────┐ ┌──────────┐ │ Loan │───→│ EMI │ │ close() │ │ dies │ └─────────────┘ └──────────┘ Loan deleted → EMIs deleted Decision: can child exist without parent? Yes → aggregation No → composition
Key Takeaway
Aggregation and composition are both HAS-A relationships but differ in lifecycle ownership. Aggregation: the child has an independent lifecycle, exists before being added to the parent, survives the parent's destruction, and can belong to multiple parents. Composition: the child's lifecycle is bound to the parent, the parent creates the child, the child has no meaning without the parent, and the child is destroyed when the parent is destroyed.
The decision rule: ask can the child exist meaningfully without the parent? If yes, aggregation (Employee without Branch is still a valid employee). If no, composition (EMI without Loan is meaningless). In JPA: aggregation has no cascade delete. Composition maps to cascade ALL with orphanRemoval.
Remember one sentence: aggregation means the child survives the parent (independent lifecycle), composition means the child dies with the parent (bound lifecycle), and the decision depends on whether the child has meaning alone.
---