Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Many-to-One Mapping

Many-to-one relationships are common in relational database systems. A classic example is a scenario where multiple employees are associated with one department, establishing a many-to-one relationship between employees and their department.

In this tutorial, we'll see how to map a many-to-one relationship using Hibernate.

Example Scenario:

Let's consider two entities, Employee and Department. An employee is associated with one department, but a department can have multiple employees.

1. Database Tables:

  • employee table: To store employee details.
  • department table: To store department details.

The employee table will have a foreign key (department_id) referring to the primary key of the department table.

2. Setting Up Dependencies:

Make sure you have Hibernate's dependencies in your project. For Maven users, this primarily means including hibernate-core.

3. Mapping Entities:

Department.java:

@Entity
@Table(name="department")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

    // constructors, getters, setters...
}

Employee.java:

@Entity
@Table(name="employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="first_name")
    private String firstName;

    @Column(name="last_name")
    private String lastName;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="department_id")
    private Department department;

    // constructors, getters, setters...
}

Explanation:

  • @ManyToOne: This annotation indicates a many-to-one relationship.
  • @JoinColumn: Specifies the name of the foreign key column that refers to the primary key of the table being joined.

4. Working with Data:

Saving:

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();

// create department and employee
Department tempDepartment = new Department("IT");

Employee tempEmployee1 = new Employee("John", "Doe");
Employee tempEmployee2 = new Employee("Mary", "Public");

// associate department with employees
tempEmployee1.setDepartment(tempDepartment);
tempEmployee2.setDepartment(tempDepartment);

// save the department and employees
session.save(tempDepartment);  // this saves the department
session.save(tempEmployee1);   // this saves employee 1
session.save(tempEmployee2);   // this saves employee 2

session.getTransaction().commit();

Retrieving:

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();

// fetch employee with id=1
Employee tempEmployee = session.get(Employee.class, 1);

// print department of that employee
System.out.println(tempEmployee.getDepartment());

session.getTransaction().commit();

5. FetchType:

  • FetchType.LAZY: With this setting, the associated entity (Department in this case) isn't loaded unless it's accessed. This helps to optimize performance by avoiding unnecessary database hits. In our example, when you fetch an employee, the department isn't loaded until you call tempEmployee.getDepartment().

Conclusion:

Mapping many-to-one relationships in Hibernate is straightforward and aligns with the relational model of databases. It's crucial to understand the cascading and fetching strategies, as well as when and how to use them to optimize performance and ensure that the database's state remains consistent with the object model in the application.

  1. Configuring many-to-one associations in Hibernate:

    • In Hibernate, many-to-one mapping is used to represent a relationship between two entities where one entity has a reference to another.
    • Configuration involves defining the many-to-one element in the Hibernate XML mapping file or using annotations.
    <!-- XML Mapping -->
    <many-to-one name="employee" class="com.example.Employee" column="employee_id" />
    
    // Annotation Mapping
    @ManyToOne
    @JoinColumn(name = "employee_id")
    private Employee employee;
    
  2. Mapping many-to-one relationships with Hibernate annotations:

    • Many-to-one relationships can be mapped using annotations by using the @ManyToOne annotation on the reference variable in the entity class.
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
    
  3. Lazy loading with many-to-one associations in Hibernate:

    • Lazy loading is a technique where associated entities are loaded only when accessed.
    • Use fetch = FetchType.LAZY to enable lazy loading.
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
    
  4. Bidirectional many-to-one mapping in Hibernate:

    • Bidirectional many-to-one mapping involves having a reference in both entities.
    • Use mappedBy attribute in the @ManyToOne annotation to establish bidirectional mapping.
    // In Employee class
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
    
    // In Department class
    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
    
  5. Cascading operations in Hibernate many-to-one mapping:

    • Cascading allows propagating operations (save, update, delete) from one entity to its associated entities.
    • Use cascade attribute in the @ManyToOne annotation.
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "department_id")
    private Department department;
    
  6. Fetching strategies in Hibernate many-to-one associations:

    • Hibernate supports different fetching strategies: select, join, subselect.
    • Define the strategy using the fetch attribute.
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
    
  7. HQL queries for many-to-one associations in Hibernate:

    • Use HQL (Hibernate Query Language) to perform queries involving many-to-one associations.
    String hql = "FROM Employee e WHERE e.department.name = :deptName";
    Query query = session.createQuery(hql);
    query.setParameter("deptName", "IT");
    List<Employee> employees = query.list();
    
  8. Handling foreign key constraints in many-to-one mapping:

    • Ensure that foreign key constraints are properly defined in the database schema.
    @ManyToOne
    @JoinColumn(name = "department_id", foreignKey = @ForeignKey(name = "FK_EMPLOYEE_DEPARTMENT"))
    private Department department;