In Hibernate, you can use the @OneToMany
and @ManyToOne
annotations to map a one-to-many relationship. Below is a step-by-step explanation with an example:
Explanation:
- One-To-Many Side: Use the
@OneToMany
annotation on the field representing the collection in the parent entity. Typically, this will be aList
,Set
, or other collection type. - Many-To-One Side: Use the
@ManyToOne
annotation on the field in the child entity referring to the parent. - Join Column or Mapped By: You can use the
@JoinColumn
annotation or themappedBy
attribute to specify the ownership of the relationship:- The
@JoinColumn
annotation is used on the owning side. - The
mappedBy
attribute is used on the side that is not the owner of the relationship.
- The
Example Scenario
- Entities: A
Department
has manyEmployee
objects, and eachEmployee
belongs to oneDepartment
.
Code Example
Parent Entity: Department
import jakarta.persistence.*;
import java.util.List;
@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;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
Child Entity: Employee
import jakarta.persistence.*;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "department_id") // Foreign key column in the Employee table
private Department department;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
Explanation of Important Annotations:
- Department Class:
@Entity
: Marks the class as a persistent entity.@OneToMany(mappedBy = "department")
:mappedBy
indicates the field in theEmployee
entity that maps the relationship (department
in this case).cascade = CascadeType.ALL
: Any operation (persist, merge, remove, etc.) applied toDepartment
is propagated to the relatedEmployee
entities.orphanRemoval = true
: Removes orphaned employees if they are no longer associated with a department.
- Employee Class:
@ManyToOne
: Establishes the many-to-one relationship with theDepartment
entity.@JoinColumn(name = "department_id")
: Specifies the foreign key column in theEmployee
table that refers to theDepartment
table.
Resulting Schema
Assuming the above mappings:
DEPARTMENT
Table:ID
: Primary keyNAME
: Department name
EMPLOYEE
Table:ID
: Primary keyNAME
: Employee nameDEPARTMENT_ID
: Foreign key referencingDEPARTMENT.ID
Additional Notes
- Bidirectional vs Unidirectional:
- The above example shows a bidirectional mapping (both
Department
andEmployee
reference each other). - If you only need unidirectional mapping, you can remove the
List<Employee>
collection from theDepartment
class.
- The above example shows a bidirectional mapping (both
- Lazy vs Eager Loading:
- By default, collections (
@OneToMany
) are lazily loaded, while single entities (@ManyToOne
) are eagerly loaded. You can explicitly define fetch strategies usingfetch = FetchType.LAZY
orfetch = FetchType.EAGER
.
- By default, collections (