Mapping - @OneToMany and @ManyToOne

In a one-to-many relationship, a single entity is associated with multiple instances of another entity. This tutorial will demonstrate how to implement a one-to-many mapping using JPA with an example leveraging EntityManager.


Example Scenario

Let’s assume the following:

  1. Department: Represents a department in an organization.
  2. Employee: Represents employees belonging to a department.

Each department can have multiple employees, but an employee belongs to only one department.


Step-by-Step Implementation

Step 1: Create Entity Classes

  1. Department Entity
import jakarta.persistence.*; import java.util.ArrayList; 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 = new ArrayList<>(); // 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 addEmployee(Employee employee) { employees.add(employee); employee.setDepartment(this); // Establish bi-directional relationship } public void removeEmployee(Employee employee) { employees.remove(employee); employee.setDepartment(null); // Break bi-directional relationship } }
  1. Employee Entity
import jakarta.persistence.*; @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToOne @JoinColumn(name = "department_id", referencedColumnName = "id") 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; } }

Step 2: Persistence Configuration

Configure your persistence.xml:

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1"> <persistence-unit name="example-unit"> <class>Department</class> <class>Employee</class> <properties> <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:testdb"/> <property name="jakarta.persistence.jdbc.user" value="sa"/> <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/> <property name="jakarta.persistence.jdbc.password" value=""/> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>

Step 3: Using EntityManager

Create a main class to demonstrate the relationship.

import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class OneToManyExample { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // Create Department Department department = new Department(); department.setName("Engineering"); // Create Employees Employee emp1 = new Employee(); emp1.setName("Alice"); Employee emp2 = new Employee(); emp2.setName("Bob"); // Establish relationships department.addEmployee(emp1); department.addEmployee(emp2); // Persist department (employees are persisted automatically due to CascadeType.ALL) em.persist(department); em.getTransaction().commit(); // Fetch and display Department fetchedDept = em.find(Department.class, department.getId()); System.out.println("Department: " + fetchedDept.getName()); System.out.println("Employees:"); fetchedDept.getEmployees().forEach(emp -> System.out.println(" - " + emp.getName())); em.close(); emf.close(); } }

Key Points:

  1. Mapping Annotations:

    • @OneToMany: Declares the relationship in the parent entity.
    • @ManyToOne: Declares the relationship in the child entity.
    • @JoinColumn: Specifies the foreign key in the child table.
  2. Cascade Operations:

    • CascadeType.ALL: Ensures that changes (persist, remove, etc.) in Department are cascaded to its employees.
  3. Orphan Removal:

    • orphanRemoval = true: Ensures that when an Employee is removed from the Department list, it is also deleted from the database.
  4. EntityManager:

    • Use em.persist() to save the Department, and the related Employee instances are persisted automatically.

Comments