Hibernate has become the de-facto ORM (Object Relational Mapping) framework for most of the organizations today. It provides a very simple framework to overcome the cumbersome techniques involved with core JDBC implementations. Whenever there is a project based on database intrinsic activities it is advisable to use Hibernate than do JDBC coding. It saves a huge amount of time revolving around unnecessary chores.

Having said that, the major question which strikes anyone who does majorly JDBC is that how does a Hibernate DAO layer look like. Without looking at a practical implementation one cannot be easily convinced to work on it. This is the only compelling reason why I intended to write The Great Hibernate Tutorial.

This tutorial is aimed at those developers who want to get a quick breifing on how to implement a DAO layer using Hibernate. This tutorial does not cover the basics of ORM nor a detailed explanation of Hibernate configurations or api. It follows on the same route as the Great Ant tutorial which many readers liked.

5 Steps to Designing a DAO in Hibernate:

  1. Identify the tables which are required as entities in your project
  2. Create the Hibernate Configuration file
  3. Create the Hibernate entity mapping files (hbm) and entity classes
  4. Make the DAO layer with the required functions
  5. Test the DAO classes

Required Softwares

The versions of the various open source software’s required for the implementation are

So lets get going with the Great Hibernate Tutorial. The steps will explain you the specific details from the code while the actual code is present in the format of links at the bottom of this tutorial. You can open the links in different tabs of your browser and then start reading the tutorial for getting a better understanding.

Step 1. Identify the tables which are required as entities in your project

For the tutorial I am designing a basic Attendance System for a company which currently has only two tables Employee and Dept. If your MySQL is not setup at the moment you may visit the tutorial on how to setup Mysql in windows XP.

 
CREATE TABLE `employee` (                                                                                       
            `psno` int(11) NOT NULL default '0',                                                                          
            `name` varchar(50) default NULL,                                                                              
            `pass` varchar(50) default NULL,                                                                              
            `proj_cd` varchar(45) NOT NULL,                                                                               
            `dept_name` varchar(45) NOT NULL,                                                                             
            PRIMARY KEY  USING BTREE (`psno`),                                                                            
            KEY `FK_employee_newfk` (`proj_cd`,`dept_name`),                                                              
            CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`proj_cd`, `dept_name`) REFERENCES `dept` (`PROJ_CD`, `DEPT_NAME`)  
          ) 
 
 
CREATE TABLE `dept` (                   
          `PROJ_CD` varchar(45) NOT NULL,       
          `DEPT_NAME` varchar(45) NOT NULL,     
          `START_DATE` date default NULL,       
          `TYPE` varchar(45) default NULL,      
          PRIMARY KEY  (`PROJ_CD`,`DEPT_NAME`)  
        )

The Employee and Dept have a one to many relationship. From the DDL it is evident that Dept table has composite keys. Usually composite keys are considered evil , but I am using it just for the sake of presenting a use case of configuring composite keys in hibernate.

Step 2. Create the Hibernate Configuration file

The Hibernate configuration file is where you provide all the connection level details. It is very straightforward configuration and appears similar to your JDBC connection statements. But unlike JDBC, you can specify many more things here like caching, dialects, debug queries. One important aspect of this configuration file is providing path of hbm files. Check the following two line of XML.

<mapping resource="com/abc/entities/Employee.hbm.xml"/>     
<mapping resource="com/abc/entities/Dept.hbm.xml"/>

These lines are important. They specify the paths to your entity mapping files. Entity mapping files are those XML files which tell hibernate as to how the entity classes relate to the tables. It defines how the data should flow from class properties to the table columns. But you have to be careful in mentioning the paths to the mapping files. It is not required that the files be kept in the packages as I have done but it is considered a convention.

Step 3. Create the Hibernate entity mapping files (hbm) and entity classes

In this step we would be actually defining the mapping. I have kept all the entities in the package com.abc.entities along with the mapping files. The first element is obvious <hibernate-mapping>. Within this element you would most of the times define 3 elements: Class, ID and Property.

Class – the class for which mapping to the table is being defined

<class name="com.abc.entities.Employee" table="employee" lazy="false">

One extra attribute of the element you would notice is lazy=”false”. This is the lazy loading technique of ORM the details of which are beyond the scope of this tutorial. You may even not mention it.

ID – Primary key is an absolute must in hibernate mapped tables. Primary Keys are mapped to ID as follows

<id name="psno" column="psno">
	<generator class="assigned" />
</id>

Generator means how the primary key is populated. If it was auto generated in the table then the value should have been “auto“. The value “assigned” means we will set it in the application itself. In case of Dept, since composite key exists we should define it as

<composite-id name="deptPK" class="com.abc.entities.DeptPK">
	<key-property name="projCode" column="PROJ_CD" />
	<key-property name="deptName" column="DEPT_NAME" />
</composite-id>

Property – These are columns which would be made as properties having getters and setters in the class definition

<property name="name"/>

this would map name property of Employee class to the name column of employee table.

Associations in Hibernate

The above 3 are majorly used. Apart from that you can also mention cardinality mapping if required as follows:

<many-to-one name="dept" class="com.abc.entities.Dept">
	<column name="proj_cd" not-null="true"/>
	<column name="dept_name" not-null="true"/>
</many-to-one>

Since I have a composite key in Dept table I have mentioned two columns in the above mapping. This mapping can be read as “MANY Employees are related TO ONE Dept with help of COLUMNS proj_cd and dept_name“. These mappings are called as Associations in hibernate.

In the Dept mapping file since one dept can return multiple Employees, they would be returned in the form of a set. Hence we would have to map the set of Employee as:

<set name="employees" inverse="true">
	<key>
		<column name="proj_cd"/>
		<column name="dept_name"/>
	</key>
	<one-to-many class="com.abc.entities.Employee" />
</set>

The inverse=”true” says that the association is bidirectional which is another important concept in hibernate. In a bidirectional relationship you can reach an associated element from within one element and same applies the other way too. On the contrary you may even have unidirectional relationship in which you don’t specify mapping in the other classes.

Defining Entity classes

This is straight forward. Entity classes are simple Java Beans. You can view the class definition in the links provided at the bottom of this post. A no argument public constructor is a must in case you define a custom one.

One special case here would be for composite keys. Composite keys are defined in a separate class. After this, In the class where composite keys are required you would have to make a property of the composite-class-type.

Step 4. Make the DAO layer with the required functions

Finally we are the moment of salvation. The thing which we were waiting eagerly for implementing. The DAO layer. It is always a good practice to make a separate DAO class for holding utility functions. Hibernate requires that you always open a session before accessing the database and making transactions when you update the database. This requires repeatable lines of code.

So in order to avoid repeating ourselves its better to keep these lines of code in a DAO class as shown in the links below. Check for com.abc.dao.DAO.java. You may use the class as it is since it is a routine code. For coding your own classes to make use of the utility functions in the DAO extend your class with this DAO.

Lets have a look at AdminDAO. Since I belive in interface based implementations I have provided AdminDAO as an interface and AdminDAOHibernateImpl as its implementation which extends DAO. The code is kept simple for understanding purposes. The things worth pondering are:

In functions which do an update on the tables you have to carry the following steps:

  1. begin();
  2. getSession()….; // save or update
  3. commit();
  4. rollback();  //in case of HibernateException and throw any custom business exception if required

For fetching data you don’t need transactions so you don’t need to do the above steps. In this case you can just execute a query via the getSession() as follows:

Query q = getSession().createQuery("from Employee e inner join fetch e.dept where e.psno = :psno");
q.setString("psno", psno.toString());
Employee emp = (Employee) q.uniqueResult();

Hibernate Query Language

The above query syntax is called HQL (Hibernate Query Language). It is syntactically very similar to JDBC with the difference that HQL queries are based on objects and not on tables so the names are case sensitive and aliases to objects are a must.

In HQL, you can either fetch a single result when you know that there would be exactly one row fetched. When you know that mutiple records might be returned then you can fetch the list as follows:

Query q = getSession().createQuery("from Employee");
List<Employee> list = q.list();
return list;

Paging in Hibernate

You can obtain paging in Hibernate very easily without any additional efforts by applying a max results criteria

q.setFirstResult(firstResult);
q.setMaxResults(maxResults);

Doesn’t it feel really good. JDBC users might feel jealous at this time1

Step 5. Test the DAO classes

Now, to our final strike. The testing can be done with POJO’s. For the tutorial I had created a service layer since I usally access teh DAO layer through the service layer. So the testing was done on the service layer instead of the DAO as this application was small. You can however test out directly the DAO functions.

static void listTest(){
	try {
		List<Employee> employees = adminService.getAllEmployees();
		for(Employee emp: employees)
			System.out.println(emp.toString());
	} catch (AppException e) {
	System.out.println(e.getMessage());
	}
}

Wasn’t that a breeze? I hope that it was. Once you gain a thorough knowledge of ORM concepts then you would appreciate working with Hibernate even more. For further knowledge, I would recommend you to go through the impedence mismatch theory to know the fundamental flaws surrounding JDBC. Working with Hibernate would then be real fun.

Enjoy folks!

Resources for the tutorial

The below files are required for running the above tutorial. Copy these to your eclipse project and add the required libraries of hibernate and mysql before running the project.

Configuration
hibernate.cfg.xml

Package: com.abc.entities
com.abc.entities.Employee.java
Employee.hbm.xml
com.abc.entities.Dept.java
com.abc.entities.DeptPK.java
Dept.hbm.xml

Package: com.abc.dao
com.abc.dao.DAO.java
com.abc.dao.AdminDAO.java
com.abc.dao.AdminDAOHibernateImpl.java

Package: com.abc.service
com.abc.service.AdminService.java
com.abc.service.AdminServiceImpl.java
com.abc.service.DeptService.java
com.abc.service.DeptServiceImpl.java

Package: com.abc.exceptions
com.abc.exceptions.AppException.java

Package: com.abc.tests
com.abc.tests.DeptTest.java


Stumble Digg Technorati Subscribe Delicious