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

Hunor Vadasz-Perhat - Feb 10 - - Dev Community

πŸš€ 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! πŸš€

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .