Enterprise Java

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:

Many To Many

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 Qualificationentities 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

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<>();
    
    ...
}

Many-to-Many association has two sides – the owning and the inverse/referencing sideThe 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 @JoinTableannotation 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 employeequalification 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.

Published on Java Code Geeks with permission by Shubhra Srivastava, partner at our JCG program. See the original article here: Hibernate Many To Many Tutorial

Opinions expressed by Java Code Geeks contributors are their own.

Shubhra Srivastava

Shubhra is a software professional and founder of ProgrammerGirl. She has a great experience with Java/J2EE technologies and frameworks. She loves the amalgam of programming and coffee :)
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
4 years ago

Hi,
Can you just clarify what the mappedBy annotation below refers to:

@ManyToMany(mappedBy = “qualifications”)
private Set employees = new HashSet();

Is it referring the instance variable of Employee class i.e.

public class Employee {

Set qualifications

?

Thanks in advance

Shubhra
4 years ago
Reply to 

Yes, you are right!
mappedBy specifies the relationship field or property of the owning entity

Back to top button