Collection Mapping in Hibernate

Hibernate supports collection mapping as value type. In this mapping, the collection are mapped into a separate table.

When we have to persist property of a class, which is of data type like integer, long, float etc. or objects of wrapper classes or Strings, these properties are stored in the table of class directly. However if the class property is collection type, we need an additional collection table to save this property.

Hibernate supports following collection interfaces as value type:

  • java.util.Set – java.util.HashSet is used to store value.
  • java.util.SortedSet – java.util.TreeSet is used to store value.
  • java.util.List – java.util.ArrayList is used to store value. Preserves the position with an index column
  • Bag semantics – java.util.ArrayList is used to store valre however the position is not preserved.
  • java.util.Map – java.util.HashMap is used to store value.
  • java.util.SortedMap – java.util.TreeMap is used to store value.

Hibernate supports collection mapping as value type. In this mapping, the collection are mapped into a separate table.

When we have to persist property of a class, which is of data type like integer, long, float etc. or objects of wrapper classes or Strings, these properties are stored in the table of class directly. However if the class property is collection type, we need an additional collection table to save this property.

Hibernate supports following collection interfaces as value type:

  • java.util.Set – java.util.HashSet is used to store value.
  • java.util.SortedSet – java.util.TreeSet is used to store value.
  • java.util.List – java.util.ArrayList is used to store value. Preserves the position with an index column
  • Bag semantics – java.util.ArrayList is used to store valre however the position is not preserved.
  • java.util.Map – java.util.HashMap is used to store value.
  • java.util.SortedMap – java.util.TreeMap is used to store value.



Mapping A Set

In this example we will map a property of type set. To start with, we will create a class Employee with properties employeeId , employeeName and phoneNumbers .Here we want to store Phones for a Student. There are more than one Phone for a Student so phoneNumbers should be declared as collection type.We need to create two tables corresponding to Student and Phone. However we do not want to expose Phone The code for this class is shown bellow:

Employee.java
package com.javawebtutor.hibernate;

import java.util.Set;

public class Employee {
	private int employeeId;
	private String employeeName;
	private Set<String> phoneNumbers;

	public int getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(int employeeId) {
		this.employeeId = employeeId;
	}

	public String getEmployeeName() {
		return employeeName;
	}

	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;
	}

	public Set<String> getPhoneNumbers() {
		return phoneNumbers;
	}

	public void setPhoneNumbers(Set<String> phoneNumbers) {
		this.phoneNumbers = phoneNumbers;
	}

}

Create the mapping file for Persistent class :

Right click on your package then navigate to New -> File and provide the name as Employee.hbm.xml and click Finish.

Add bellow code into Employee.hbm.xml file

Employee.hbm.xml
<?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.javawebtutor.hibernate.Employee" table="EMPLOYEE">
          <id name="employeeId">
          <generator class="increment"></generator>
          </id>
          <property name="employeeName"></property>
          
          <set name="phoneNumbers" table="EMP_PHONE_NUMBERS">
          <key column="phoneid"></key>
          <element column="phone_number" type="string"></element>
          </set>
          
          </class>
   
          
          
          </hibernate-mapping>

The above xml has a <set> declaration to declare that property whose name is phoneNumbers is of Set type.

<key column="phoneid" />

The above lines declares the name of foreign key column in EMP_PHONE_NUMBERS that references to the primary key of the owning entity, employeeId in this case.

Note :-If your database column name and persistence class variable is same then no need to specify column property in .hbm file.



Create the Configuration file :

The configuration file contains informations about the database and mapping file. Conventionally, its name should be hibernate.cfg.xml .Configuration file must be in classpath of your Project.Place this file in src of your project by default it will added to classpath of your project.

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>
		<!-- specify database driver -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url"> jdbc:mysql://localhost/hibernate</property>
		<!-- database username -->
		<property name="hibernate.connection.username">root</property>
		<!-- database password -->
		<property name="connection.password">mukesh</property>
		<!-- database dialect, different for different databases -->
		<property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</property>
		<!-- true value shows SQL query that is generated by hibrnate -->
		<property name="show_sql">true</property>

		<property name="hbm2ddl.auto">update</property>
		<!-- to bind hibernate session to current running java thread -->
		<property name="current_session_context_class">thread</property>
		<!-- path of hibernate mapping file -->
		<mapping resource="com/javawebtutor/hibernate/Employee.hbm.xml"></mapping>
	</session-factory>
</hibernate-configuration>

Create Test class :

Create a java class Test which will persist and load the Employee class instances. Code for this class is given below.

Test.java
package com.javawebtutor.hibernate;

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

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class Test {

	public static void main(String[] args) {
		Session session = new Configuration().configure("hibernate.cfg.xml")
				.buildSessionFactory().openSession();
		Transaction t = session.beginTransaction();

		Employee employee = new Employee();
		employee.setEmployeeName("Mukesh");
		Set phoneNumbers = new HashSet();
		phoneNumbers.add("123456");
		phoneNumbers.add("231252");
		phoneNumbers.add("863426");
		employee.setPhoneNumbers(phoneNumbers);
		session.save(employee);
		t.commit();

		Query query = session.createQuery("from Employee");
		List list = query.list();

		Iterator itr = list.iterator();
		while (itr.hasNext()) {
			Employee emp = itr.next();
			System.out.println("Employee Name: " + emp.getEmployeeName());

			// printing answers
			Set set = emp.getPhoneNumbers();
			Iterator itr2 = set.iterator();
			while (itr2.hasNext()) {
				System.out.println(itr2.next());
			}
		}

		session.close();
		System.out.println("success");

	}
}

Run the Application :

To run the hibernate application, right click on the Test class - Run As - Java Application.

Output in Eclipse :

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into EMPLOYEE (employeeName, employeeId) values (?, ?)
Hibernate: insert into EMP_PHONE_NUMBERS (phoneid, phone_number) values (?, ?)
Hibernate: insert into EMP_PHONE_NUMBERS (phoneid, phone_number) values (?, ?)
Hibernate: insert into EMP_PHONE_NUMBERS (phoneid, phone_number) values (?, ?)
Hibernate: select employee0_.employeeId as employeeId0_, employee0_.employeeName as employee2_0_ from EMPLOYEE employee0_
Employee Name: Mukesh
863426
123456
231252
success

In The Database :


mysql> select * from employee;
+------------+--------------+
| employeeId | employeeName |
+------------+--------------+
|          0 | Mukesh       |
+------------+--------------+
1 row in set (0.00 sec)

mysql> select * from emp_phone_numbers;
+---------+--------------+
| phoneid | phone_number |
+---------+--------------+
|       0 | 863426       |
|       0 | 123456       |
|       0 | 231252       |
+---------+--------------+
3 rows in set (0.00 sec)

You can download the source code of the example by clicking on the Download link below.

Source + Lib : Download




comments powered by Disqus