Other Tutorials

Hibernate Many To Many Tutorial

Introduction:

In this tutorial, we’ll learn to define and use a many-to-many entity association using Hibernate @ManyToMany annotation.

Context BuildUp:

To follow along with this tutorial, let’s say we have two entities – Employee and Qualification:

ManyToMany Hibernate Relationship

As we know, one employee can multiple qualifications. Also, there can be N number of employees with a specific qualification. It clearly means that the Employee and Qualification entities share a Many-to-Many relationship.

Maven Dependencies:

In our POM, let’s first ensure we have the required dependencies:

<dependencies>
    ...
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.4.0.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.13</version>
    </dependency>
    ...
</dependencies>

We can always find out the latest available version at the Maven Central. Also, we’re using MySQL database for this tutorial.

Database Setup:

To represent a ManyToMany association, we’ll at least need three database tables. So, let’s say we have the below ERD diagram representing our database:

Many To Many ERD Diagram

Also, let’s create our tables:

CREATE TABLE employee (
    emp_id INT(15) NOT NULL AUTO_INCREMENT,
    first_name VARCHAR(20) DEFAULT NULL,
    last_name  VARCHAR(20) DEFAULT NULL,
    PRIMARY KEY (emp_id)
);

CREATE TABLE qualification (
    qualification_id INT(15) NOT NULL AUTO_INCREMENT,
    title VARCHAR(20) DEFAULT NULL,
    PRIMARY KEY (qualification_id)
);

CREATE TABLE employee_qualification (
    emp_id INT(15) NOT NULL,
    qualification_id INT(15) NOT NULL,
    PRIMARY KEY (emp_id, qualification_id),
    CONSTRAINT employee_qualification_empIdFk 
      FOREIGN KEY (emp_id) REFERENCES employee(emp_id),
    CONSTRAINT employee_qualification_qualIdFk 
     FOREIGN KEY (qualification_id) REFERENCES qualification (qualification_id)
);

Creating Entities:

Now that we have our database setup ready, let’s first create the model class – Employee:

@Entity
@Table(name = "Employee")
public class Employee { 
    // ...
  
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "Employee_Qualification", 
        joinColumns = { @JoinColumn(name = "emp_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "qualification_id") }
    )
    Set<Qualification> qualifications = new HashSet<>();
    
    ...
}

A Many-to-Many association has two sides – the owning and the inverse/referencing side. The actual physical mapping to the database is specified on the owning side of the relationship. Here, Employee is the owning entity and so we have used the @JoinTable annotation to define the actual physical database mapping. The @JoinTable annotation defines our employee_qualification join table.

The @JoinColumn annotation specifies the column that’ll be used to join the tables. We have also mentioned that qualification_id would be the inverse join column. It simply means it refers to the inverse side of the relationship which is our Qualification class.

Let’s now define our Qualification entity class:

@Entity
@Table(name = "Qualification")
public class Qualification {    
    // ...  
  
    @ManyToMany(mappedBy = "qualifications")
    private Set<Employee> employees = new HashSet<>();
     
    ...
}

Since Qualification class is the referencing or the inverse side of the association, we have used the mappedBy attribute to refer to its owning side (Employee).

Also as we can see, we have used @ManyToMany annotation in both of our entities.

Using Many-To-Many Association:

In our main() method, we can test out the above mapping:

//In our MainApp class
public static void main(String[] args) {
    Session session = null;    
    try {
        SessionFactory factory = new Configuration()
          .configure().buildSessionFactory();
        session = factory.openSession();
        Transaction tranx = session.beginTransaction();

        Employee james = new Employee(1001, "James", "Allen");
        Employee selena = new Employee(1002, "Selena", "Gomez");
        
        Set<Employee> employees = new HashSet<>();
        employees.add(james);
        employees.add(selena);
        
        Qualification masters = 
          new Qualification(8787, "Masters Degree");
        masters.setEmployees(employees);     
        
        session.save(masters);
        tranx.commit();
    } catch(Exception e) {
        e.printStackTrace();
    }
    finally {
        if(session != null)
            session.close();
    }

}

On executing the above code, our test data would have been inserted in our employee, qualification and employee_qualification tables.

Conclusion:

In this mini-tutorial, we looked at how to establish a ManyToMany JPA association. We have used JPA annotations over the plain-old XML configurations as they are more convenient to use and are becoming increasingly popular.

One comment
Pingback: Hibernate Many To Many Tutorial | Hey Android - Android World

Leave a Comment

Your email address will not be published. Required fields are marked *