Hibernate One To Many Mapping Tutorial

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

Figure 2.1 Figure 2.1

According to the relationship each Employee can have any number of phone numbers. The relational model is shown below in Figure 2.2

Figure 2.2 Relational Database (one to many relationship)
Figure 2.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 Phone(
    Phone_Id int(10) primary key NOT NULL AUTO_INCREMENT,
    EMPLOYEE_ID int(10),
    Type varchar(50),
    Number varchar(50),
    Foreign Key(EMPLOYEE_ID)  References Employee(EMPLOYEE_ID));

2. Pojo

Now create Employee and Phone Class as following.

Employee.java


package com.kruders.model.bean;

import java.util.Set;

public class Employee {
	private int employeeId;
	private String name;
	private Set<Phone> phone;
	public Employee() {
	}
	public Employee(String name) {
		this.name = name;
	}
	public Employee(String name, Set<Phone> phone) {
		this.name = name;
		this.phone = phone;
	}

	
	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<Phone> getPhone() {
		return phone;
	}
	public void setPhone(Set<Phone> phone) {
		this.phone = phone;
	}
}


Phone.java

package com.kruders.model.bean;


public class Phone {
	private long phoneId;
	private String type;
	private String number;
	private Employee employee;
	public Phone() {
	}
	public Phone(Employee employee, long phoneId, String type, String number) {
		this.employee = employee;
		this.phoneId = phoneId;
		this.type = type;
		this.number = number;
	}
	
	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public long getPhoneId() {
		return phoneId;
	}
	public void setPhoneId(long phoneId) {
		this.phoneId = phoneId;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
}

To map Employee and Phone 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="phone" table="phone" 
				inverse="true" lazy="true" fetch="select">
    	<key>
        	<column name="EMPLOYEE_ID" not-null="true" />
        </key>
        <one-to-many class="com.kruders.model.bean.Phone" />
    </set>
</class>
</hibernate-mapping>

We use one-to-many element in Employee Table and many-to-one element in Phone Table to create the one-to-many relationship between the Employee and Phone entities.

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

<?xml version="1.0"?>

<!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.Phone" table="PHONE">
		<id name="phoneId" type="long" column="Phone_Id">
			<generator class="native" />
		</id>
		<property name="type" type="string" length="10" column="Type" />
		<property name="number" type="string" length="15"
			column="Number" />
		<many-to-one name="employee" class="com.kruders.model.bean.Employee" fetch="select">
            <column name="EMPLOYEE_ID" not-null="true" />
        </many-to-one>
	</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"></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/Phone.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.model.bean.Phone;
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 employee = new Employee("Raghav");
			session.save(employee);
			
			Phone phone = new Phone();
			phone.setType("Office");
			phone.setNumber("1234567890");
			phone.setEmployee(employee);
			session.save(phone);
			
			transaction.commit();
		}catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		
		//listEmployee();
		//updateEmployee("Raghav", "1234567890", "0123456789");
		//deleteEmployee("Raghav", "0123456789");
	}
	
	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());
				for(Phone phone : employee.getPhone()) {
					System.out.println("Type " + phone.getType());
					System.out.println("Number " + phone.getNumber());
				}
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	public void updateEmployee(String oldName, String oldNumber, String newNumber) {
		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();
				for(Phone phone : employee.getPhone()) {
					if(phone.getNumber().equals(oldNumber)) {
						phone.setNumber(newNumber);
					}
				}
				
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	public void deleteEmployee(String name, String number) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			
			transaction = session.beginTransaction();
			List employees = session.createQuery("from Employee where Name ='" + name + "'").list();
			for (Iterator iterator = employees.iterator(); iterator.hasNext();) {
				Employee employee = (Employee) iterator.next();
				for(Phone phone : employee.getPhone()) {
					if(phone.getNumber().equals(number)) {
						System.out.println("Number " + phone.getNumber());
						session.delete(phone);
					} else {
						System.out.println("Number1 " + phone.getNumber());
					}
				}
			}
			
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
}

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

Figure 2.3 Figure 2.3

You can download the source code of this example here.


One-to-Many <bag> example


A Bag is a java collection that stores elements without caring about the sequencing but allow duplicate elements in the list. A bag is a random grouping of the objects in the list.
A Collection is mapped with a element in the mapping table and initialized with java.util.ArrayList.

To implement Bag in our one-to-many mapping example, we have to change in following two files:

1. Employee.java

private Set<Phone> phone;

New Code


private List<Phone> phone;


2. Employee.hbm.xml


<set name=”phone” table=”phone” inverse=”true” lazy=”true” fetch=”select”>
<key>
<column name=”EMPLOYEE_ID” not-null=”true” />
</key>
<one-to-many class=”com.kruders.model.bean.Phone” />
</set>

New Code

<bag name=”phone” table=”phone” inverse=”true” lazy=”true” fetch=”select”>
<key>
<column name=”EMPLOYEE_ID” not-null=”true” />
</key>
<one-to-many class=”com.kruders.model.bean.Phone” />
</bag>

You can download the source code of this example here.

One Response to Hibernate One To Many Mapping Tutorial

  1. ajay mittal June 1, 2013 at 11:05 am #

    hi i am gettingfollowing exception kindly help me out:

    org.hibernate.exception.ConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`selene7`.`menu_action_id_list`, CONSTRAINT `FK287EF31950855CD3` FOREIGN KEY (`fld_circle_id`, `fld_profile_id`, `element_type`, `action_id`, `element_id`) REFERENCES `action_details` (`fld_ci)
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    at com.sun.proxy.$Proxy5.executeUpdate(Unknown Source)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
    at com.onmobile.cbc.dstk.client.Demo.saveMultipleObjects(Demo.java:354)
    at com.onmobile.cbc.dstk.client.Demo.saveChanges(Demo.java:301)
    at com.onmobile.cbc.dstk.client.Demo.main(Demo.java:398)
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`selene7`.`menu_action_id_list`, CONSTRAINT `FK287EF31950855CD3` FOREIGN KEY (`fld_circle_id`, `fld_profile_id`, `element_type`, `action_id`, `element_id`) REFERENCES `action_details` (`fld_ci)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.Util.getInstance(Util.java:381)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
    … 15 more

Leave a Reply