Introduction
In Hibernate, the most commonly used collection mapping is List. Along with List, we have other collection mappings such as Bag, Set, Map, SortedSet, SortedMap, and so on. However, mapping lists are the preferred method in many places because they have an index element, making searching and performing CRUD operations easier.
A List is a type of Java collection that stores elements in sequential order and allow duplicate elements. The user of this interface has complete control over where each element is inserted in the list. The user can access elements by integer index and search the list for elements. Lists typically allow pairs of elements a and b such that a equals b, and they typically allow multiple null elements if null elements are allowed.
Hibernate List Mapping Procedure
We will now discuss the mapping procedure step by step in detail.
Define RDBMS Tables
Consider the following scenario for the hibernate list mapping:
We need to store employee records in the EMPLOYEE table, which will have the following structure:
create table EMPLOYEE (id INT NOT NULL,
first_name VARCHAR(30),
last_name VARCHAR(30),
salary INT,
PRIMARY KEY (id)
);
Assume that each employee can be associated with one or more certificates. A collection table index column is required for a List collection mapping. The index column specifies the element's position in the collection. As a result, we will store certificate information in a separate table with the following structure:
create table CERTIFICATE (
id INT NOT NULL,
name VARCHAR(30),
index INT,
employee_id INT,
PRIMARY KEY (id)
);
EMPLOYEE and CERTIFICATE objects will have a one-to-many relationship.
Define POJO Classes
The next step in hibernate list mapping is defining POJO classes.
Let us create a POJO class Employee that will be used to persist objects related to the EMPLOYEE table and a collection of certificates in the List variable.
import java.util.*;
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
private List certificates;
public Employee() {}
public Employee(String firstName, String lastName, int salary) {
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
}
public void setId( int id ) {
this.id = id;
}
public int getId() {
return id;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
public List getCertificates() {
return certificates;
}
public void setCertificates( List certificates ) {
this.certificates = certificates;
}
}
Another POJO class corresponding to the CERTIFICATE table must be defined so that certificate objects can be stored and retrieved from the CERTIFICATE table.
public class Certificate{
private int id;
private String name;
public Certificate() {}
public Certificate(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
}Define Hibernate Mapping File
Let's create a mapping file that tells Hibernate how to map the defined classes to the database tables. The list> element will be used to specify the List collection rule. The index of a list is mapped with the <list-index> element and is always of the integer type.
<?xml version = "1.1" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate_mapping>
<class name = "EmployeeData" table = "EMPLOYEES">
<meta attribute = "class-description">
Contains the employee data.
</meta>
// defining id
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<list name = "certificates" cascade="all">
<key column = "employee_id"/>
<list-index column = "index"/>
<one-to-many class="Certificate"/>
</list>
<property name = "lastName" column = "last-name" type = "string"/> <property name = "firstName" column = "first-name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
<class name = "Certificate" table = "CERTIFICATE">
<meta attribute = "class-description">
This class contains certificates.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "name" column = "certificate-name" type = "string"/>
</class>
</hibernate_mapping>
The mapping document should be saved in a file with the extension .hbm.xml. Employee.hbm.xml is the name we gave to our mapping document.
Elements of the mapping file
-
The mapping document is an XML document with <hibernate-mapping> as root element that contains two <class>> elements, one for each class.
-
The <class> elements specify specific mappings between Java classes and database tables. The name attribute of the class element is used to specify the Java class name, and the table attribute is used to specify the database table name.
-
The <meta> element is optional and can be used to generate the class description.
-
The <id> element maps the class's unique ID attribute to the database table's primary key. The column attribute of the id element points to the column in the table, and the name attribute refers to the property in the class. The type attribute contains the hibernate list mapping type, which converts Java data to SQL data types.
-
Within the id element, the <generator> element is used to automatically generate the primary key values. The class attribute of this element is put to native, which instructs hibernate to use either the identity, sequence, or Hilo algorithms to generate the primary key, depending on the capabilities of the database.
-
The <list> element establishes the connection between the Certificate and Employee classes. We used the element's cascade attribute to instruct Hibernate to persist the Certificate objects alongside the Employee objects. The name attribute is set to the parent class's defined List variable, which in our case is certificates.
-
The <property> element maps a database table column to a Java class property. The element's name attribute refers to the property in the class, while the column attribute refers to the column in the database table. The type attribute contains the hibernate list mapping type, which converts Java data to SQL data types.
-
The <key> element is that column in the CERTIFICATE table that contains the foreign key to the parent object, EMPLOYEES.
-
The <list-index> element stores the element's position and maps it to the collection table's index column. By default, the persistent list's index begins at zero, which can be changed as desired.
- The <one-to-many> element suggests that one Employee object is related to multiple Certificate objects, and thus the Certificate object must have an Employee parent. Depending on your needs, you can use <one-to-one>, <many-to-one> or <many-to-many> elements. If we switched this example to a many-to-many relationship, we'd need an association table to map the parent and child objects.
Create Application Class
Finally, we'll create our application class, including the main() method for running the application. This application will be used to save a few Employee records along with their certificates, and then we will perform CRUD operations on those records.
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ManageE = new ManageEmployee();
/*Set of certificates for the first employee */
ArrayList set1 = new ArrayList();
set1.add(new Certificate("MCA"));
set1.add(new Certificate("MBA"));
set1.add(new Certificate("BBA"));
/* Add employee records in the database */
Integer empID1 = ManageE.add("Rakesh", "Patel", 8000, set1);
/*Set of certificates for the second employee */
ArrayList set2 = new ArrayList();
set2.add(new Certificate("BBA"));
set2.add(new Certificate("BA"));
/* Add another employee record in the database */
Integer empID2 = ManageE.add("Harish", "Kumar", 5000, set2);
/* List down all the employees */
ManageE.listEmployees();
/* Update employee's salary records */
ManageE.updateSalary(empID1, 5000);
/* Delete an employee from the database */
ManageE.deleteEmployee(empID2);
/* List down all the employees */
ManageE.listEmployees();
}
/* adding an employee record in the database */
public Integer add(String fname, String lname, int salary, ArrayList cert){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employees employee = new Employees(fname, lname, salary);
employee.setCertificates(cert);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to list all the employees detail */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator1 = employees.iterator(); iterator1.hasNext();){
Employees employee = (Employee) iterator1.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
List certificates = employee.getCertificates();
for (Iterator iterator2 = certificates.iterator(); iterator2.hasNext();){
Certificate certName = (Certificate) iterator2.next();
System.out.println("Certificate: " + certName.getName());
}
}
tx.commit();
}
catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/*Updating salary for an employee */
public void updateSalary(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employees employee = (Employees)session.get(Employees.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
}
catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* deleting an employee from the records */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employees employee = (Employee)session.get(Employees.class, EmployeeID);
session.delete(employee);
tx.commit();
}
catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}Compiling and Execution
The following are the steps to compile and run the application, as mentioned earlier. Before proceeding with the compilation and execution, ensure that PATH and CLASSPATH have been properly set.
- Create the hibernate.cfg.xml configuration file.
- As shown above, create the Employee.hbm.xml mapping file.
- Create and Compile the Employee.java source file
- Create and Compile the Certificate.java source file
- Create and Compile the ManageEmployee.java source file
- To run the program, run the ManageEmployee binary.
The screen would display the following result, and records would be created simultaneously in the EMPLOYEE and CERTIFICATE tables. As you can see, the certificates are sorted in reverse order. You can experiment by changing your mapping file; simply set sort="natural" to run your code, and compare the results.
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Rakesh Last Name: Patel Salary: 8000
Certificate: MCA
Certificate: MBA
Certificate: BBA
First Name: Harish Last Name: Kumar Salary: 5000
Certificate: BBA
Certificate: BA
First Name: Rakesh Last Name: Patel Salary: 5000
Certificate: MCA
Certificate: MBA
Certificate: BBA
If you look through your EMPLOYEE and CERTIFICATE tables, you should find the following records:
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 51 | Rakesh | Patel | 8000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)
mysql> select * from CERTIFICATE;
+----+------------------+------+-------------+
| id | certificate_name | idx | employee_id |
+----+------------------+------+-------------+
| 6 | MCA | 0 | 51 |
| 7 | MBA | 1 | 51 |
| 8 | BBA | 2 | 51 |
+----+------------------+------+-------------+
3 rows in set (0.00 sec)
mysql>
You could also map a Java array instead of a list. An array mapping is nearly identical to the previous example, except that the element and attribute names (array> and array-index> are different. However, for the reasons stated previously, Hibernate applications rarely use arrays.
Check out this problem - First And Last Occurrences Of X





