In our previous article, we introduced you to the concept of Valye Type Object in Hibernate and displayed its use using Annotations in Hibernate. Today,
we will explain the concept of Valye Type Object in Hibernate by creating the mapping-resource file with extension hbm.xml, instead of Annotations.
For those who have not read our previous article about Value Type Object, here is the recap.
A Value type object in Hibernate and is different from an Entity object.
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, while
Value Type object is an object of another class but it is stored as a part of Entity object within a database table.
Entity class v/s Value Type class
Let's suppose, we have two classes Employee_Details and Credentials,
where Employee_Details contains the information about the identification number, first name and last name of each employee
and Credentials class refers to the information such as skills, number of years of experience and awards received by each employee.
Without an Entity object, a Value Type object has no value, i.e. a
Credentials object has no value unless it is associated with an Employee_Details object, or, if we don't know the Employee's first name,
last name and ID, can a single Credentials object is
going to help us know which employee it belongs to? No, because many people may have similar credentials.
A Value Type class does not need to have a primary key and its objects depends on the primary key of Entity class, hence
an instance of Credentials is dependent on the instance of Employee_Details.
A Value Type object has no database identity of its own and it is embedded within the same row of its associated Entity class object,
within a single database table i.e. each object of Credentials is stored as a part of each Employee_Details object.
Let's put this example to work to have a better understanding of the concept.
Note :
In the upcoming example, We are going to create a Java Entity class and a Value Type 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),
so 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.
Employee_Details.java
package decodejava;
public class Employee_Details
{
private int id;
private String firstName;
private String lastName;
private Credentials credentials;
public Credentials getCredentials()
{
return credentials;
}
public void setCredentials(Credentials credentials)
{
this.credentials = credentials;
}
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;
}
}
Creating the Value Type class
Next, we are going to create the Value Type class that will contain a specific piece information about each employee, such as -
skills, awards received and years of experience. Many people within an organisation could possess the similar set of skills, years of experience etc
hence, this class has no value on its own.
A Value Type class is only valuable when it is used in combination with the Entity class i.e.
when a Value Type object is embedded within an Entity object in the same database table as the Entity class.
Credentials.java
package decodejava;
public class Credentials
{
private int yearsOfExp;
private String awards;
private String skills;
public int getYearsOfExp()
{
return yearsOfExp;
}
public void setYearsOfExp(int yearsOfExp)
{
this.yearsOfExp = yearsOfExp;
}
public String getAwards()
{
return awards;
}
public void setAwards(String awards)
{
this.awards = awards;
}
public String getSkills()
{
return skills;
}
public void setSkills(String skills)
{
this.skills = skills;
}
}
Advertisement
Creating the class that calls the Hibernate API - Utility class
This class will create some Employee_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.
Hiber.java
package decodejava;
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 Employee object
Employee_Details ob1 = new Employee_Details();
ob1.setFirstName("John");
ob1.setLastName("Smith");
Credentials cred_Ob1 = new Credentials();
cred_Ob1.setAwards("Employee of the year - 2016");
cred_Ob1.setSkills("Java, JavaScript, C++");
cred_Ob1.setYearsOfExp(5);
ob1.setCredentials(cred_Ob1);
//Creating the second Employee object
Employee_Details ob2 = new Employee_Details();
ob2.setFirstName("Shawn");
ob2.setLastName("Webber");
Credentials cred_Ob2 = new Credentials();
cred_Ob2.setAwards("Employee of the year - 2014");
cred_Ob2.setSkills("ASP.NET, JavaScript, C++");
cred_Ob2.setYearsOfExp(7);
ob2.setCredentials(cred_Ob2);
//Creating the third Employee object
Employee_Details ob3 = new Employee_Details();
ob3.setFirstName("Mika");
ob3.setLastName("Hekkin");
Credentials cred_Ob3 = new Credentials();
cred_Ob3.setAwards("Employee of the year - 2017");
cred_Ob3.setSkills("Django, C, C++");
cred_Ob3.setYearsOfExp(4);
ob3.setCredentials(cred_Ob3);
//Saving all the objects in the database using Hibernate
session.beginTransaction();
session.save(ob1); //Saving the first object
session.save(ob2); //Saving the second object
session.save(ob3); //Saving the third object
session.getTransaction().commit();
session.close();
sf.close();
}
}
Adding the mapping-resource file
Following the same steps using which we created and added the configuration file in our project, 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 and Value Type class to a table in the database and perform the object-relational mapping. This is also an XML file and we are going to name this
file employeedetails.cfg.xml.
This mapping document ends with an extension .hbm.xml,
hence, we have named it employeedetails.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.Employee_Details" table = "EMPLOYEE_DETAILS">
<id name = "id" column = "USER_ID" type = "int">
<generator class="native"/>
</id>
<property name = "firstName" column = "First_Name" type = "string"/>
<property name = "lastName" column = "Last_Name" type = "string"/>
<component name="credentials" class="decodejava.Credentials">
<property name="yearsOfExp"/>
<property name="awards"/>
<property name="skills"/>
</component>
</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 component element maps a value type object to be saved within the current object mapping(in the same the database table).
the name child attribute refers to the name of a property to map.
The class child attribute refers to name of a value type class.
The property child attribute maps a property within a value type class to a column in the current object mapping
(in the same the database table).
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.
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 Entity class and value type object 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>
<!--Naming the mapping resource file -->
<mapping resource ="employeedetails.hbm.xml"/>
</session-factory>
</hibernate-configuration>
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.
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 - HibernateValueTypeObject 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. Employee_Details.java, our Value type class i.e. Credentials.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 we have specified the mapping-resource file i.e.
employeedetails.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, when you run the following SQL query in the database -
select * from EMPLOYEE_DETAILS;
you will get the following output, as shown below.
This output shows that each object of Value Type class is stored as a part of an object of the Entity class, within a single database table.