Hibernate Self Join One to Many Mapping

In this tutorial I will show you how to implement Self-Join One to Many mapping , via XML mapping file (hbm).

Figure 9.1 illustrates Self Reference one-to-many relationship.

Figure 9.1 Figure 9.1

According to this relationship each employee can have manager and each manager is an employee.

First create a new Java Project and configure it as Maven Project. For Reference, Click Here

Add the following dependencies in pom.xml

<dependencies>
 
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>
 
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.15</version>
    </dependency>
 
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.6.3.Final</version>
    </dependency>
 
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.6</version>
    </dependency>
</dependencies>

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),
    manager_id int(10) REFERENCES employee (employee_id));

2. Pojo

Now create Employee Class as following.

Employee.java


package com.kruders.model.bean;

import java.util.Set;

public class Employee {
	private int employeeId;
	private String name;
	private Integer managerId;
	private Set employees;
	
	private Employee manager;
	
	public Set getEmployees() {
		return employees;
	}
	public void setEmployees(Set employees) {
		this.employees = employees;
	}
	public Employee getManager() {
		return manager;
	}
	public void setManager(Employee manager) {
		this.manager = manager;
	}
	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 Integer getManagerId() {
		return managerId;
	}
	public void setManagerId(Integer managerId) {
		this.managerId = managerId;
	}
}

manager attribute is mapped with many-to-one tag and employees attribute is mapped with one-to-many tag as shown in hibernate mapping file.

3. Hibernate Mapping File

Now create HBM file Employee.hbm.xml that maps classes to database tables.

<?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="managerId" type="int" update="false"
            insert="false" column="manager_id" length="10"/>
	<property name="name" type="string" length="50" column="NAME" />
	<many-to-one name="manager" class="com.kruders.model.bean.Employee" column="manager_id"
            not-null="false"/>
    <set name="employees" table="EMPLOYEE" lazy="false" cascade="all-delete-orphan" 
            inverse="false">
              <key column="manager_id"/>
              <one-to-many 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"/>
</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 org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

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 manager = new Employee("Puneet");
	        
	        Employee employee1 = new Employee("Sahil");
	        Employee employee2 = new Employee("Geet");
	        
	        employee1.setManager(manager);
	        employee2.setManager(manager);
	        session.save(manager);
			//session.save(employee1);
			//session.save(employee2);
			transaction.commit();
		}catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		
		//listEmployee();
		//updateEmployee("Puneet", "Raghav");
		//listEmployee();
		//deleteEmployee(72);
	}
	
	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("Name " + employee.getName());
               
            }
            transaction.commit();
        } catch (HibernateException e) {
            transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
	
	public void updateEmployee(String oldName, String newName) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
        try {
             
            transaction = session.beginTransaction();
            List employees = session.createQuery("from Employee where Name ='" + oldName + "'").list();
            for (Iterator iterator = employees.iterator(); iterator.hasNext();) {
                Employee employee = (Employee) iterator.next();
                employee.setName(newName);
            }
            transaction.commit();
        } catch (HibernateException e) {
            transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
	     
    public void deleteEmployee(Integer employeeId) {
    	Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
        try {
             
            transaction = session.beginTransaction();
            List<Employee> employees = session.createQuery("from Employee where employeeId ='" + employeeId + "'").list();
            for(Employee employee : employees) {
            	System.out.println("Name " + employee.getName());
            	session.delete(employee);
            }
           
            transaction.commit();
        } catch (HibernateException e) {
            transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
}

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

Figure 9.2 Figure 9.2

You can download the source code of this example here.

2 Responses to Hibernate Self Join One to Many Mapping

  1. Ravi Krishna P July 30, 2013 at 6:22 am #

    This is a very good explanation through example. I was wondering if you can give an example or situation where manager which is Employee type, i don’t want to pull that complete record of manager. I just want manager’s id which is employee_id. Is that possible?. What i fell cascade.All would do is pull all the recurring records and create reference objects of type Employee. But i just want on level and just manager_id which Integer rather to have whole record of that manger.

  2. Satendra September 18, 2013 at 10:02 am #

    Hi Why am getting this error
    As i have imported your project after downloading and included the required jar file.
    org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: com.kruders.model.bean.Employee

Leave a Reply