Hibernate Many To Many Mapping Tutorial

In this tutorial I will show how to do Many to Many mapping using Hibernate. Figure 3.1 illustrates many-to-many relationship, via XML mapping file (hbm).

Figure 3.1 Figure 3.1

According to the relationship each Employee can works in more than one Department and each Department can have more than one Employee. The relational model is shown below in Figure 3.2

Figure 3.2 Relational Database (many to many relationship)
Figure 3.2

1. Sql Script

Use the following Sql Script for creating table.


create table Employee(
    EMPLOYEE_ID int(10) primary key NOT NULL AUTO_INCREMENT,
    Name varchar(50));
 
create table Department(
    Department_ID int(10) primary key NOT NULL AUTO_INCREMENT,
    Department_Name varchar(50));
 
create table Employee_Department(
    EMPLOYEE_ID int(10) not null,
    Department_ID int(10) not null,
    primary key( EMPLOYEE_ID, Department_ID),
    foreign key( EMPLOYEE_ID) references Employee ( EMPLOYEE_ID),
    foreign key( Department_ID) references Department( Department_ID));

2. Pojo

Now create Employee and Department Class as following.

Employee.java


package com.kruders.model.bean;

import java.util.HashSet;
import java.util.Set;


public class Employee {
	private int employeeId;
	private String name;
	private Set<Department> departments = new HashSet<Department>();
	public Employee() {
	}
	public Employee(String name) {
		this.name = name;
	}

	
	public int getEmployeeId() {
		return employeeId;
	}
	public void setEmployeeId(int employeeId) {
		this.employeeId = employeeId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Department> getDepartments() {
		return departments;
	}
	public void setDepartments(Set<Department> departments) {
		this.departments = departments;
	}
}


Department.java

package com.kruders.model.bean;

import java.util.HashSet;
import java.util.Set;

public class Department {
	private int departmentId;
	private String departmentName;
	private Set<Employee> employees = new HashSet<Employee>();
	
	public Department() {
	}
	
	public Department(String departmentName) {
		this.departmentName = departmentName;
	}

	public int getDepartmentId() {
		return departmentId;
	}

	public void setDepartmentId(int departmentId) {
		this.departmentId = departmentId;
	}

	public String getDepartmentName() {
		return departmentName;
	}

	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}

	public Set<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}
	
}

To map Employee and Department table you need to create the following hibernate mapping files.

3. Hibernate Mapping File

Employee.hbm.xml is used to map the Employee table.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.kruders.model.bean.Employee" table="EMPLOYEE">
	<meta attribute="class-description">This class contains employee details.</meta>
	<id name="employeeId" type="int" column="EMPLOYEE_ID">
		<generator class="native" />
	</id>
	<property name="name" type="string" length="50" column="NAME" />
	<set name="departments" table="Employee_Department"
            inverse="false" lazy="true" fetch="select" cascade="all">
            <key column="EMPLOYEE_ID" />
            <many-to-many column="DEPARTMENT_ID" class="com.kruders.model.bean.Department" />
    </set>

</class>
</hibernate-mapping>

We use many-to-many element to create many-to-many relationship between the Employee and Department entities.
Department.hbm.xml is used to map the Department table.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping>
 
    <class name="com.kruders.model.bean.Department" table="DEPARTMENT">
 
        <id name="departmentId" type="int"
            column="DEPARTMENT_ID">
            <generator class="native" />
        </id>
 
        <property name="departmentName" column="Department_Name" />
       
        <set name="employees" table="Employee_Department"
            inverse="true" lazy="true" fetch="select">
            <key column="Department_ID" />
            <many-to-many column="EMPLOYEE_ID" class="com.kruders.model.bean.Employee" />
        </set>
 
    </class>
</hibernate-mapping>

4. Hibernate Configuration File

Now create the hibernate configuration file and add all the mapping files.
hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">password</property>
	<property name="connection.pool_size">1</property>
	<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
	<property name="show_sql">true</property>
	<mapping resource="com/kruders/model/bean/Employee.hbm.xml"/>
	<mapping resource="com/kruders/model/bean/Department.hbm.xml"/>
</session-factory>
</hibernate-configuration>

5. Hibernate Utility Class

Now create HibernateUtil class. The HibernateUtil class helps in creating the SessionFactory from the Hibernate configuration file. A org.hibernate.SessionFactory is used to obtain org.hibernate.Session instances. A org.hibernate.Session represents a single-threaded unit of work. The org.hibernate.SessionFactory is a thread-safe global object that is instantiated once.

package com.kruders.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
  
public class HibernateUtil {
  
    private static final SessionFactory sessionFactory = buildSessionFactory();
  
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

6. Run Program

Create Main.java class that perform CRUD operations and run it as Java Application

package com.kruders.core;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.kruders.model.bean.Department;
import com.kruders.model.bean.Employee;
import com.kruders.util.HibernateUtil;



public class Main {
	public static void main(String args[]) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			
			transaction = session.beginTransaction();
			Employee employee1 = new Employee("Raghav");
			Employee employee2 = new Employee("Puneet");
			
			Department department1 = new Department("Lab");
			Department department2 = new Department("Library");
			
			employee1.getDepartments().add(department1);
			employee1.getDepartments().add(department2);
			
			employee2.getDepartments().add(department1);
			session.save(employee1);
	        session.save(employee2);
			
			
			transaction.commit();
		}catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		
		//listEmployee();
		//updateEmployee("Puneet", "Lab", "HR");
		//deleteEmployee("Puneet", "HR");
	}
	
	public void listEmployee() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			
			transaction = session.beginTransaction();
			List employees = session.createQuery("from Employee").list();
			for (Iterator iterator = employees.iterator(); iterator.hasNext();) {
				Employee employee = (Employee) iterator.next();
				System.out.println("Employee Name " + employee.getName());
				for(Department department : employee.getDepartments()) {
					System.out.println("Department Name " + department.getDepartmentName());
				}
			}
			
			System.out.println("Now Getting Department and their Employees");
			List departments = session.createQuery("from Department").list();
			for (Iterator iterator = departments.iterator(); iterator.hasNext();) {
				Department department = (Department) iterator.next();
				System.out.println("Department Name " + department.getDepartmentName());
				for(Employee employee : department.getEmployees()) {
					System.out.println("Employee Name " + employee.getName());
				}
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	public void updateEmployee(String oldName, String oldDepartment, String newDepartment) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			Boolean departmentExists = false;
			transaction = session.beginTransaction();
			List<Department> departments = session.createQuery("from Department where Department_Name ='" + newDepartment + "'").list();
			List<Employee> employees = session.createQuery("from Employee where Name ='" + oldName + "'").list();
			for(Employee employee : employees)  {
				Set<Department> tempdepartments = employee.getDepartments();
				for(Department department : tempdepartments) { 
					if(department.getDepartmentName().equals(oldDepartment)) {
						System.out.println("Department " + department.getDepartmentName());
						employee.getDepartments().remove(department);
						if(departments.size() > 0) {
							employee.getDepartments().add(departments.get(0));
						} else {
							Department dept = new Department(newDepartment);
							employee.getDepartments().add(dept);
						}
					}
				}
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	public void deleteEmployee(String name, String departmentName) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			
			transaction = session.beginTransaction();
			List<Employee> employees = session.createQuery("from Employee where Name ='" + name + "'").list();
			for(Employee employee : employees)  {
				Set<Department> departments = employee.getDepartments();
				for(Department department : departments) { 
					if(department.getDepartmentName().equals(departmentName)) {
						System.out.println("Department " + department.getDepartmentName());
						employee.getDepartments().remove(department);
					}
				}
			}
			
			
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
}

The folder structure of the example is shown below in Figure 3.3

Figure 3.3 Figure 3.3

You can download the source code of this example here.

No comments yet.

Leave a Reply