hibernate-010: Bidirectional One-to-Many & Many-to-One in Hibernate
Hunor Vadasz-Perhat

Hunor Vadasz-Perhat @hunor85

About: Software Engineer II @DXC Technology

Location:
Denmark
Joined:
Jul 3, 2023

hibernate-010: Bidirectional One-to-Many & Many-to-One in Hibernate

Publish Date: Feb 10
0 0

🚀 Bidirectional One-to-Many & Many-to-One in Hibernate

Now, let’s fully explore bidirectional One-to-Many and Many-to-One relationships with real examples, database schema, and queries.


📌 1️⃣ What is a Bidirectional One-to-Many & Many-to-One?

  • One parent entity has multiple child entities (One-to-Many).
  • Each child entity belongs to one parent entity (Many-to-One).
  • The "Many" side owns the foreign key, and the "One" side is mapped using mappedBy.

✅ Best Practice

  • The child (Many) owns the relationship (@ManyToOne with @JoinColumn).
  • The parent (One) just references it (@OneToMany(mappedBy = "field")).

📌 2️⃣ Example: Department ↔ Employee

  • One Department has many Employees (@OneToMany).
  • Each Employee belongs to one Department (@ManyToOne).

✅ Step 1: Define @ManyToOne (Owning Side - Employee)

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "department_id") // ✅ Foreign key in Employee table
    private Department department;
}
Enter fullscreen mode Exit fullscreen mode

✅ The department_id foreign key is stored in Employee.


✅ Step 2: Define @OneToMany(mappedBy = "department") (Inverse Side - Department)

@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "department") // ✅ Refers to Employee.department
    private List<Employee> employees = new ArrayList<>();
}
Enter fullscreen mode Exit fullscreen mode

mappedBy = "department" tells Hibernate:

  • "The foreign key is already in Employee.department_id."
  • "Don’t create an extra join table."

📌 3️⃣ Database Schema (No Extra Join Table!)

CREATE TABLE department (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255)
);

CREATE TABLE employee (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    department_id BIGINT, -- ✅ Foreign key column
    FOREIGN KEY (department_id) REFERENCES department(id)
);
Enter fullscreen mode Exit fullscreen mode

✅ The foreign key is only in Employee.department_id, keeping the relationship correct.


📌 4️⃣ Saving Data in Hibernate

Department department = new Department();
department.setName("IT Department");

Employee emp1 = new Employee();
emp1.setName("Alice");
emp1.setDepartment(department); // ✅ Set reference in Employee

Employee emp2 = new Employee();
emp2.setName("Bob");
emp2.setDepartment(department);

department.getEmployees().add(emp1); // ✅ Set reference in Department
department.getEmployees().add(emp2);

entityManager.persist(department);
entityManager.persist(emp1);
entityManager.persist(emp2);
Enter fullscreen mode Exit fullscreen mode

🚀 Now both Department and Employee are correctly linked!


📌 5️⃣ Querying Both Directions

Get Employees from Department

Department dept = entityManager.find(Department.class, 1L);
List<Employee> employees = dept.getEmployees();
employees.forEach(emp -> System.out.println(emp.getName())); // ✅ Works!
Enter fullscreen mode Exit fullscreen mode

Get Department from Employee

Employee emp = entityManager.find(Employee.class, 10L);
System.out.println(emp.getDepartment().getName()); // ✅ Works!
Enter fullscreen mode Exit fullscreen mode

Both queries work because the relationship is bidirectional.


📌 6️⃣ Summary: One-to-Many & Many-to-One

Feature One-to-Many (Department) Many-to-One (Employee)
@OneToMany(mappedBy = "department") ✅ Yes ❌ No
@ManyToOne used? ❌ No ✅ Yes
@JoinColumn(name = "fk_column") ❌ No ✅ Yes
Foreign key location? ❌ Not in Department ✅ In Employee.department_id
Extra join table? ❌ No ❌ No
Reference back? ✅ Yes ✅ Yes

Best Practice: Use bidirectional @OneToMany + @ManyToOne to avoid unnecessary join tables and keep data consistent.


Happy coding! 🚀

Comments 0 total

    Add comment