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
@OneToManyannotation 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
@ManyToOneannotation on the field in the child entity referring to the parent. - Join Column or Mapped By: You can use the
@JoinColumnannotation or themappedByattribute to specify the ownership of the relationship:- The
@JoinColumnannotation is used on the owning side. - The
mappedByattribute is used on the side that is not the owner of the relationship.
- The
Example Scenario
- Entities: A
Departmenthas manyEmployeeobjects, and eachEmployeebelongs 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"):mappedByindicates the field in theEmployeeentity that maps the relationship (departmentin this case).cascade = CascadeType.ALL: Any operation (persist, merge, remove, etc.) applied toDepartmentis propagated to the relatedEmployeeentities.orphanRemoval = true: Removes orphaned employees if they are no longer associated with a department.
- Employee Class:
@ManyToOne: Establishes the many-to-one relationship with theDepartmententity.@JoinColumn(name = "department_id"): Specifies the foreign key column in theEmployeetable that refers to theDepartmenttable.
Resulting Schema
Assuming the above mappings:
DEPARTMENTTable:ID: Primary keyNAME: Department name
EMPLOYEETable:ID: Primary keyNAME: Employee nameDEPARTMENT_ID: Foreign key referencingDEPARTMENT.ID
Additional Notes
- Bidirectional vs Unidirectional:
- The above example shows a bidirectional mapping (both
DepartmentandEmployeereference each other). - If you only need unidirectional mapping, you can remove the
List<Employee>collection from theDepartmentclass.
- 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.LAZYorfetch = FetchType.EAGER.
- By default, collections (
