How do I map a one-to-many relationship using Hibernate annotations?

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:

  1. One-To-Many Side: Use the @OneToMany annotation on the field representing the collection in the parent entity. Typically, this will be a List, Set, or other collection type.
  2. Many-To-One Side: Use the @ManyToOne annotation on the field in the child entity referring to the parent.
  3. Join Column or Mapped By: You can use the @JoinColumn annotation or the mappedBy 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.

Example Scenario

  • Entities: A Department has many Employee objects, and each Employee belongs to one Department.

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:

  1. Department Class:
    • @Entity: Marks the class as a persistent entity.
    • @OneToMany(mappedBy = "department"):
      • mappedBy indicates the field in the Employee entity that maps the relationship (department in this case).
      • cascade = CascadeType.ALL: Any operation (persist, merge, remove, etc.) applied to Department is propagated to the related Employee entities.
      • orphanRemoval = true: Removes orphaned employees if they are no longer associated with a department.
  2. Employee Class:
    • @ManyToOne: Establishes the many-to-one relationship with the Department entity.
    • @JoinColumn(name = "department_id"): Specifies the foreign key column in the Employee table that refers to the Department table.

Resulting Schema

Assuming the above mappings:

  • DEPARTMENT Table:
    • ID: Primary key
    • NAME: Department name
  • EMPLOYEE Table:
    • ID: Primary key
    • NAME: Employee name
    • DEPARTMENT_ID: Foreign key referencing DEPARTMENT.ID

Additional Notes

  • Bidirectional vs Unidirectional:
    • The above example shows a bidirectional mapping (both Department and Employee reference each other).
    • If you only need unidirectional mapping, you can remove the List<Employee> collection from the Department class.
  • Lazy vs Eager Loading:
    • By default, collections (@OneToMany) are lazily loaded, while single entities (@ManyToOne) are eagerly loaded. You can explicitly define fetch strategies using fetch = FetchType.LAZY or fetch = FetchType.EAGER.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.