Today we are going to understand how to persist a collection object based on a Set collection interface i.e. HashSet, within the database using Hibernate.
HashSet stores the collection of elements in an unsorted order.
Why do we have to add a collection object in an Entity class.
Let's suppose we have a class Companies containing the information such as - id, name and a
Set collection of String object(representing names of all the employees of a particular company), and
that's why we are going to need a collection object in Companies class, to represent multiple employee names in a company.
Let's put this example to work and make it easier for you to understand the whole concept.
Note :
In the upcoming example, We are going to create a Java Entity class which will be mapped to a table in our database(Oracle Express Edition 10g).
To perform this, we are not going to use Hibernate Annotations, we will instead create the mapping-resource file with extension hbm.xml.
And yes, one more thing, we are going to create this program in an Eclipse Integrated Development Environment (IDE),
though you may use any IDE of your choice.
Creating a POJO/Entity class
We are creating a simple Java Entity class whose objects are also known as Plain Old Java Objects(POJO) or Entity objects.
The objects of this class(containing the HashSet collection object)
need to be persisted/saved.
This collection object is stored in a separate table, while the Entity object is stored in a separate table in the database.
Some may even refer to this Entity class as the Model class.
Companies.java
package decodejava;
import java.util.Set;
public class Companies
{
private int id;
private String companyName;
private Set<String> employeeNames = new HashSet<String>();
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
public Set<String> getEmployeeNames()
{
return employeeNames;
}
public void setEmployeeNames(Set<String> employeeNames)
{
this.employeeNames = employeeNames;
}
}
Advertisement
Creating a Utility class that calls the Hibernate API
This class Hiber.java will create an object of Companies Entity class , which will be persisted using the Hibernate API and an
object-relational mapping(ORM) in the database is performed.
Hiber.java
package decodejava;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Hiber
{
public static void main(String... ar)
{
Configuration config = new Configuration();
SessionFactory sf = config.configure().buildSessionFactory();
Session session = sf.openSession();
//Creating the first Company
Companies company1 = new Companies();
company1.setCompanyName("Company1");
//Creating the second Company
Companies company2 = new Companies();
company2.setCompanyName("Company2");
//Creating a set collection of employees of the first company
Set<String> collection1 = new HashSet<String>();
collection1.add("CM1_Employee1");
collection1.add("CM1_Employee2");
collection1.add("CM1_Employee3");
//Setting the collection of the employees to the first company
company1.setEmployeeNames(collection1);
//Creating a set collection of employees of the second company
Set<String> collection2 = new HashSet<String>();
collection2.add("CM2_Employee1");
collection2.add("CM2_Employee2");
collection2.add("CM2_Employee3");
//Setting the set collection of the employees to the second company
company2.setEmployeeNames(collection2);
session.beginTransaction();
session.save(company1);
session.save(company2);
session.getTransaction().commit();
session.close();
//Creating a new Session to retrieve the objects.
session= sf.openSession();
session.beginTransaction();
company1 = (Companies)session.get(Companies.class,1);
company2 = (Companies)session.get(Companies.class,2);
System.out.println("Retrieving the saved objects");
System.out.println("Name of the first company : "+ company1.getCompanyName());
Set<String> employeeNames1 = company1.getEmployeeNames();
System.out.println(employeeNames1);
System.out.println("Retrieving the saved objects");
System.out.println("Name of the second company : "+ company2.getCompanyName());
Set<String> employeeNames2 = company2.getEmployeeNames();
System.out.println(employeeNames2);
}
}
The Hiber class creates a Configuration object, used to configure the Hibernate. This is the first object we use when using the Hibernate.
This object is used to specify the location of a configuration file and
mapping document used by Hibernate. Using the Configuration object, we can create a SessionFactory object, which is eventually used to create a Session
object to perform the object persistence operations.
Adding JARs
We are going to add some JARs files to the build path of our Java project.
These JARs make the Hibernate work with our database using a specific JDBC Driver for our particular
database.
All these JARs are included in the folder named required(within the Hibernate installation folder).
So, we need to add all the JARs in the required to our build path of our Java project.
Finally, we are going to add one more JAR file.
This is a specific JDBC JAR file(ojdbc14.jar) required by Hibernate to connect to our database(Oracle Express Edition 10g) and perform
object-relational mapping and object persistence.
Next, we are going to create and add a mapping-resource file within our package decodejava.
This file allows Hibernate to map the Model/Entity class to a table in the database and perform the object-relational mapping.
This mapping document ends with an extension .hbm.xml, hence, we have named it companies.hbm.xml.
This mapping document tells Hibernate -
The name of the class to be mapped to a database table.
The name of the database table to be created.
The specific field, which is to be made the primary key in this table.
The data-type of each property in the class, which is going to mapped to a column in a table.
employeedetails.hbm.xml
<?xml version = "1.0" 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 = "decodejava.Companies" table = "COMPANIES">
<id name = "id" column = "Company_ID" type = "int">
<property name = "companyName" column = "Company_Name" type = "string"/>
<set name ="employeeNames" table="COMPANY_EMPLOYEES" cascade="all">
<key column="Company_ID"/>
<element column="Employee_Names" type="string"/>
</set>
</class>
</hibernate-mapping>
This mapping document has <hibernate-mapping> as the root element and its child element <class>, containing all the class elements.
The name attribute within the <class> element defines the name of the class to be mapped to a database table.
The table attribute within the <class> element defines the name of database table to be created for the class.
The id element maps a property within the class to the primary key of the database table.
the name child attribute refers to the name of a property in the class.
The column child attribute refers to name of a column in the database table.
The type child attribute specifies the data type of the property within the class, which will be mapped to SQL data type.
The property element maps a property within the class to a column in the database table.
the name child attribute refers to the name of a property in the class.
The column child attribute refers to the column name in the database table.
The set element maps a Set object to be saved in the another database table).
the name child attribute refers to the name of a property to map.
The table child attribute refers to the name of the table in which this Set object will be saved.
The element child attribute refers to the column name that will be created to hold Set collection of objects and
their type.
Adding a configuration file
Next, we are going to add a configuration file to our project.
This configuration document ends with an extension .cfg.xml,
and it is named as hibernate.cfg.xml.
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:XE</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<!--Naming the mapping resource file -->
<mapping resource ="companies.hbm.xml"/>
</session-factory>
</hibernate-configuration>
This configuration file is an xml file and it allows us to specify the following features -
A database to which Hibernate connects to perform object-relational mapping and object persistence.
The JDBC driver class for our specific database, used by the Hibernate to connect to the database.
The username and password of database, using which the Hibernate connects to the database.
An SQL Dialect, used by the Hibernate to instruct the database.
A command to echo all the SQL commands which are executed by the Hibernate on stdout.
The mapping resource file used by Hibernate to correctly map the parent and subclasses to a database table.
Directory Structure of Hibernate Project
The picture above depicts how and where to arrange POJO/Entity(.java) file and the other the class(that calls the hibernate into action)
in a specific directory structure.
Project Folder - HibernateWithCollection is the name of our Project and it is a top-level directory.
This project folder contains the main package of our project i.e. decodejava,
which contains POJO/Entity class file i.e. Companies.java and the class that calls the hibernate into action i.e. Hiber.java.
Besides this, the project folder also contains the hibernate configuration file i.e. hibernate.cfg.xml, and
as we have not used Hibernate Annotations in this project, hence, we have created and used a mapping-resourcecompanies.hbm.xml .
The project folder also contains all the needed Hibernate JARs present in the required folder of Hibernate
installation and the JDBC JAR file(ojdbc14.jar) required by Hibernate to connect to our database.
Execution
Finally, after executing Hiber class, two separate tables will be created in the database -
COMPANIES, which stores the Entity objects.
COMPANY_EMPLOYEES, which stores the Set collection object.
And you will get the following output, which shows the collection of employee names retrieved in a unsorted order.
Hibernate: create table COMPANIES (COMPANY_ID number(10,0) not null, Company_Name varchar2(255 char), primary key (COMPANY_ID))
Hibernate: create table COMPANY_EMPLOYEES (COMPANY_ID number(10,0) not null, Employee_Names varchar2(255 char))
Hibernate: alter table COMPANY_EMPLOYEES add constraint FKf3ir1cup274vb9nd2jrwj3hea foreign key (COMPANY_ID) references COMPANIES
Hibernate: select max(COMPANY_ID) from COMPANIES
Hibernate: insert into COMPANIES (Company_Name, COMPANY_ID) values (?, ?)
Hibernate: insert into COMPANIES (Company_Name, COMPANY_ID) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: insert into COMPANY_EMPLOYEES (COMPANY_ID, Employee_Names) values (?, ?)
Hibernate: select companies0_.COMPANY_ID as COMPANY_ID1_0_0_, companies0_.Company_Name as Company_Name2_0_0_ from COMPANIES companies0_ where companies0_.COMPANY_ID=?
Hibernate: select companies0_.COMPANY_ID as COMPANY_ID1_0_0_, companies0_.Company_Name as Company_Name2_0_0_ from COMPANIES companies0_ where companies0_.COMPANY_ID=?
Retrieving the saved objects
Name of the first company : Company1
Hibernate: select employeena0_.COMPANY_ID as COMPANY_ID1_1_0_, employeena0_.Employee_Names as Employee_Names2_1_0_ from COMPANY_EMPLOYEES employeena0_ where employeena0_.COMPANY_ID=?
[CM1_Employee2, CM1_Employee3, CM1_Employee1]
Retrieving the saved objects
Name of the second company : Company2
Hibernate: select employeena0_.COMPANY_ID as COMPANY_ID1_1_0_, employeena0_.Employee_Names as Employee_Names2_1_0_ from COMPANY_EMPLOYEES employeena0_ where employeena0_.COMPANY_ID=?
[CM2_Employee2, CM2_Employee1, CM2_Employee3]
Hence, when you run the following SQL query in the database -
select * from COMPANIES;
You will get the following output displaying the objects of COMPANIES Entity class stored in COMPANIES table, as shown below.
And on executing the following query in the database -
select * from COMPANY_EMPLOYEES;
You will get the following output displaying the Set collection object of type String, stored in COMPANY_EMPLOYEES table, as shown below.
This output shows that each object of COMPANY_EMPLOYEES and all the names of employees under column Employee_Names are sorted in an unsorted order.