JPA - One-To-Many associations explained
In JPA, a one-to-many association is a relationship where one entity is associated with multiple instances of another entity. This is typically represented using the @OneToMany annotation on the owning side of the relationship and the @ManyToOne annotation on the other side.
Key Points to Understand
- Cardinality:
- In a one-to-many relationship, one entity (the parent) is associated with multiple instances of another entity (the child). For example, a
Departmententity might have manyEmployeeentities.
- In a one-to-many relationship, one entity (the parent) is associated with multiple instances of another entity (the child). For example, a
- Owning Side:
- The many side (the child entity) is usually the owning side of the relationship because it contains the foreign key that references the primary key of the one side (the parent entity).
- Bidirectional and Unidirectional Relationships:
- Unidirectional: The parent entity knows about the child entities, but the child entities do not have a reference back to the parent. Only the
@OneToManyannotation is used. - Bidirectional: Both entities are aware of the relationship. The parent entity has a
@OneToManyannotation, and the child entity has a@ManyToOneannotation.
- Unidirectional: The parent entity knows about the child entities, but the child entities do not have a reference back to the parent. Only the
- Cascade Type and Fetch Type:
- Cascade operations can propagate changes from the parent to the children.
- Fetch type for a
@OneToManyrelationship isLAZYby default, meaning the child entities are loaded on demand.
Example
Let’s consider an example where we have two entities: Department and Employee.
Entity Classes
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Employee> employees = new ArrayList<>();
// Getters and setters
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
// Getters and setters
}
Explanation
-
Department Entity:
- The
Departmententity has aList<Employee>field annotated with@OneToMany, indicating that a department can have multiple employees. - The
mappedByattribute specifies that thedepartmentfield in theEmployeeentity owns the relationship. cascade = CascadeType.ALLensures that operations on theDepartmententity cascade to theEmployeeentities.orphanRemoval = trueensures that if anEmployeeis removed from theList<Employee>, it will also be removed from the database.
- The
-
Employee Entity:
- The
Employeeentity has adepartmentfield annotated with@ManyToOne, indicating that each employee belongs to one department. - The
@JoinColumnannotation specifies the foreign key column (department_id) in theEmployeetable that references the primary key of theDepartmententity.
- The
Database Structure
Department Table
| Column Name | Data Type | Constraints |
|---|---|---|
| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT |
| name | VARCHAR | NOT NULL |
id: The primary key for theDepartmenttable.name: A column to store the name of the department.
Employee Table
| Column Name | Data Type | Constraints |
|---|---|---|
| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT |
| name | VARCHAR | NOT NULL |
| department_id | BIGINT | FOREIGN KEY |
-
id: The primary key for theEmployeetable. -
name: A column to store the name of the employee. -
department_id: A foreign key column that references theidcolumn in theDepartmenttable. This establishes the many-to-one relationship betweenEmployeeandDepartment.
Example of Table Content
Assume we have the following data in the Department and Employee entities:
-
Department: { id: 1, name: “IT” }
-
Employees:
- { id: 101, name: “Alice”, department_id: 1 }
- { id: 102, name: “Bob”, department_id: 1 }
Department Table
| id | name |
|---|---|
| 1 | IT |
Employee Table
| id | name | department_id |
|---|---|---|
| 101 | Alice | 1 |
| 102 | Bob | 1 |
How They Work Together
- The
Employeetable’sdepartment_idcolumn references theidcolumn in theDepartmenttable, establishing a foreign key relationship. - This setup allows multiple
Employeerecords to be associated with a singleDepartment, enforcing the one-to-many relationship.
Use Cases
- One-to-many relationships are commonly used in scenarios like departments and employees, orders and order items, or any parent-child relationship where one parent entity manages multiple child entities.
This relational structure helps in organizing the data in a way that reflects the real-world relationships between entities, ensuring integrity and consistency in the database.