An Entity object is an object of our plain old java class(POJO) Model/Business class, which needs to be persisted in a database using Hibernate.
An Entity object may contain a collection object, which contains a collection of objects of another class.
This collection object is stored in a separate table, while the Entity object is stored in a separate table in the database.
So, let us understand how to persist a collection object within the database using Hibernate.
Why do we have to add a collection object in an Entity class.
Let's suppose we have two classes User_Details and Contact_Info,
where -
User_Details contains the information like id, first name and last name of each employee.
Contact_Info class refers to the information such as email address, phone number of each user.
Each user may have a couple of important email addresses or phone numbers. Hence, each user object of User_Details, could be associated with the multiple
objects of Contact_Info.
That's why we are going to need a collection object in User_Details, representing each user with multiple contact info's.
Let's put this example to work and make it easier for you to understand.
Note :
In the upcoming example, We are going to create a Java class which will be mapped to a table in our database(Oracle Express Edition 10g).
We are going to use some Hibernate Annotations in the upcoming example, hence, there will be no need to create the mapping-resource with extension hbm.xml .
For those who are not aware of Hibernate Annotations, please read
Hibernate Annotations for reference.
And yes, one more thing, we are going to create this program in an Eclipse Integrated Development Environment (IDE),
but you may use any IDE of your choice.
Creating a POJO/Entity class
We are going to create a class that will contain all the Java code files
representing our Model class(whose objects needs to be persisted)
and the class that calls the Hibernate API and create an object-relational mapping(ORM) and perform object persistence.
This is a simple Java class whose objects needs to be persisted/saved, these objects are also known as Plain Old Java Objects(POJO) or Entity class.
Some may even refer to such class whose objects needs to be persisted as the Model class.
In the upcoming Entity class, we are going to use two important annotations -
@ElementCollection - This annotation is placed just above the collection object property, which tells the Hibernate that the collection object
should be persisted as a collection and should not be embedded in the same table as the Entity objects, but as a separate table in the database.
@JoinTable - This annotations is used to name the database table that contains the collection object or a table
that is associated with the Entity object table through mapping(one-to-one, one-to-many etc).
User_Details.java
package decodejava;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table (name ="USER_DETAILS")
public class User_Details {
@Id
@GeneratedValue
@Column (name = "ID")
private int id;
@Column (name = "First_Name")
private String firstName;
@Column (name = "Last_Name")
private String lastName;
@ElementCollection
@JoinTable (name = "CONTACT_INFO")
private Set contact = new HashSet();
public Set<Contact_Info> getContact()
{
return contact;
}
public void setContact(Set contact)
{
this.contact = contact;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
}
Advertisement
Creating the collection class
Next, we are going to create the class whose objects will be persisted in a collection.
The object of this class will contain a specific piece information about each user, such as -
email address and phone number.
Many people within an organisation could possess multiple important email addresses and phone numbers,
hence, multiple objects of this class could be related to a particular User_Details object, because a user may have
multiple email addresses and phone numbers.
Hence, the multiple objects of this class will be saved as a collection in each User_Details object.
This class is only valuable when it is used in combination with the Entity class i.e. when its
object is embedded within an Entity object, which is performed by adding @Embeddable annotation at the beginning of
this class.
Contact_Info.java
package decodejava;
import javax.persistence.Embeddable;
@Embeddable
public class Contact_Info
{
private String emailId;
private String phoneNo;
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
}
Creating the class that calls the Hibernate API
This class will create some User_Details objects , which will be persisted using the Hibernate API and an
object-relational mapping(ORM) in the database is performed.
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 Configuration object we can create a SessionFactory object, which is eventually used to create a Session
object to perform the object persistence operations.
Note : We will not need to set the Id value of each object, as it is automatically done by Hibernate's sequence object by using @GeneratedValue annotation.
Hiber.java
package decodejava;
import java.util.HashSet;
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 User details
User_Details ob1 = new User_Details();
ob1.setFirstName("John");
ob1.setLastName("Smith");
//Creating the contact info for the user
Contact_Info firstUser_contact1 = new Contact_Info();
firstUser_contact1.setEmailId("email1-firstuser@email.com");
firstUser_contact1.setPhoneNo("11111111");
//Adding the first Contact_Info object to the collection
ob1.getContact().add(firstUser_contact1);
//Creating another contact info for the same user
Contact_Info firstUser_contact2 = new Contact_Info();
firstUser_contact2.setEmailId("email2-firstuser@email.com");
firstUser_contact2.setPhoneNo("22222222");
//Adding the second Contact_Info object to the collection
ob1.getContact().add(firstUser_contact2);
session.beginTransaction();
session.save(ob1); //Saving the first object
session.getTransaction().commit();
session.close();
session = sf.openSession();
//Creating the second User details
User_Details ob2 = new User_Details();
ob2.setFirstName("Nick");
ob2.setLastName("Wright");
//Creating the contact info for the user
Contact_Info secondUser_contact1 = new Contact_Info();
secondUser_contact1.setEmailId("email-seconduser@email.com");
secondUser_contact1.setPhoneNo("33333333");
//Adding the first Contact_Info object to the collection
ob2.getContact().add(secondUser_contact1);
//Creating another contact info for the same user
Contact_Info secondUser_contact2 = new Contact_Info();
secondUser_contact2.setEmailId("email2-seconduser@email.com");
secondUser_contact2.setPhoneNo("444444444");
//Adding the second Contact_Info object to the collection
ob2.getContact().add(secondUser_contact2);
session.beginTransaction();
session.save(ob2); //Saving the first object
session.getTransaction().commit();
session.close();
}
}
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 our 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 add a configuration file to our project.
This configuration document ends with an extension .cfg.xml,
and it is named as hibernate.cfg.xml.
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 Entity/POJO class which will be mapped to a database table by Hibernate.
A command to echo all the SQL commands which are executed by the Hibernate on stdout.
The mapping entity class, used by Hibernate to correctly map the class to a database table.
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">system</property>
<property name="connection.password">promila21</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>
<!-- Names the mapping entity class -->
<mapping class ="decodejava.User_Details"/>
</session-factory>
</hibernate-configuration>
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. User_Details.java, our Embeddable class i.e. Contact_Info.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 used some Hibernate Annotations in this project, hence, there will be no need to create the mapping-resource
with extension 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 -
USER_DETAILS, which stores the Entity objects.
USER_CONTACT_INFO, which stores the collection object.
Hence, when you run the following SQL query in the database -
select * from USER_DETAILS;
you will get the following output displaying the objects of User_Details Entity class stored in USER_DETAILS table, as shown below.
And on executing the second query in the database -
select * from USER_CONTACT_INFO;
you will get the following output displaying the collection object containing objects of Contact_Info class stored in USER_CONTACT_INFO table, as shown below., as shown below.
This output shows that each object of Contact_Info class is stored in a separate table than an object of the Entity class.
Note : The output clearly shows you that Hibernate has used its sequence object to generate the value of each primary key(Id) automatically as we have used @GeneratedValue
annotations with it.