Integrating Spring Framework with Hibernate ORM Framework: Part 1

by Ahmad Seddighi | November 2009 | Java Open Source

This article by Ahmad Seddighi discusses how Spring affects the application's data-access layer. Our discussion starts with the Data Access Object (DAO) pattern. This pattern, which is popular in the Java world, allows for a more manageable, more maintainable data-access tier. Then, we'll discuss how Spring affects application DAO classes when integrated with Hibernate.

Spring is a general-purpose framework that plays different roles in many areas of application architecture. One of these areas is persistence. Spring does not provide its own persistence framework. Instead, it provides an abstraction layer over JDBC, and a variety of O/R mapping frameworks, such as iBATIS SQL Maps, Hibernate, JDO, Apache OJB, and Oracle TopLink. This abstraction allows consistent, manageable data-access implementation.

Spring's abstraction layer abstracts the application from the connection factory, the transaction API, and the exception hierarchies used by the underlying persistence technology. Application code always uses the Spring API to work with connection factories, utilizes Spring strategies for transaction management, and involves Spring's generic exception hierarchy to handle underlying exceptions. Spring sits between the application classes and the O/R mapping tool, undertakes transactions, and manages connection objects. It translates the underlying persistence exceptions thrown by Hibernate to meaningful, unchecked exceptions of type DataAccessException. Moreover, Spring provides IoC and AOP, which can be used in the persistence layer. Spring undertakes Hibernate's transactions and provides a more powerful, comprehensive approach to transaction management.

The Data Access Object pattern

Although you can obtain a Session object and connect to Hibernate anywhere in the application, it's recommended that all interactions with Hibernate be done only through distinct classes. Regarding this, there is a JEE design pattern, called the DAO pattern. According to the DAO pattern, all persistent operations should be performed via specific classes, technically called DAO classes. These classes are used exclusively for communicating with the data tier. The purpose of this pattern is to separate persistence-related code from the application's business logic, which makes for more manageable and maintainable code, letting you change the persistence strategy flexibly, without changing the business rules or workflow logic.

The DAO pattern states that we should define a DAO interface corresponding to each DAO class. This DAO interface outlines the structure of a DAO class, defines all of the persistence operations that the business layer needs, and (in Spring-based applications) allows us to apply IoC to decouple the business layer from the DAO class.

Service Facade Pattern

In implementation of data access tier, the Service Facade Pattern is always used in addition to the DAO pattern. This pattern indicates using an intermediate object, called service object, between all business tier objects and DAO objects. The service object assembles the DAO methods to be managed as a unit of work. Note that only one service class is created for all DAOs that are implemented in each use case.

The service class uses instances of DAO interfaces to interact with them. These instances are instantiated from the concrete DAO classes by the IoC container at runtime. Therefore, the service object is unaware of the actual DAO implementation details.

Regardless of the persistence strategy your application uses (even if it uses direct JDBC), applying the DAO and Service Facade patterns to decouple application tiers is highly recommended.

Data tier implementation with Hibernate

Let's now see how the discussed patterns are applied to the application that directly uses Hibernate. The following code shows a sample DAO interface:

package com.packtpub.springhibernate.ch13;

import java.util.Collection;


public interface StudentDao {
public Student getStudent(long id);

public Collection getAllStudents();

public Collection getGraduatedStudents();

public Collection findStudents(String lastName);

public void saveStudent(Student std);

public void removeStudent(Student std);
}

The following code shows a DAO class that implements this DAO interface:

package com.packtpub.springhibernate.ch13;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.Query;

import java.util.Collection;

public class HibernateStudentDao implements StudentDao {

SessionFactory sessionFactory;

public Student getStudent(long id) {
Student student = null;
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
student = (Student) session.get(Student.class, new Long(id));
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
return student;
}

public Collection getAllStudents(){
Collection allStudents = null;
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Query query = session.createQuery(
"from Student std order by std.lastName, std.firstName");
allStudents = query.list();
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e; } finally {
session.close();
}
return allStudents;
}

public Collection getGraduatedStudents(){
Collection graduatedStudents = null;
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Query query = session.createQuery(
"from Student std where std.status=1");
graduatedStudents = query.list();
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
return graduatedStudents;
}

public Collection findStudents(String lastName) {
Collection students = null;
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Query query = session.createQuery(
"from Student std where std.lastName like ?");
query.setString(1, lastName + "%");
students = query.list();
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
return students;
}

public void saveStudent(Student std) {
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.saveOrUpdate(std);
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
}

public void removeStudent(Student std) {
Session session = HibernateHelper.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.delete(std);
tx.commit();
tx = null;
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
}

public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}

As you can see, all implemented methods do routines. All obtain a Session object at first, get a Transaction object, perform a persistence operation, commit the transaction, rollback the transaction if exception occurs, and finally close the Session object. Each method contains much boilerplate code that is very similar to the other methods.

Although applying the DAO pattern to the persistence code leads to more manageable and maintainable code, the DAO classes still include much boilerplate code. Each DAO method must obtain a Session instance, start a transaction, perform the persistence operation, and commit the transaction. Additionally, each DAO method should include its own duplicated exception-handling implementation. These are exactly the problems that motivate us to use Spring with Hibernate.

Template Pattern: To clean the code and provide more manageable code, Spring utilizes a pattern called Template Pattern. By this pattern, a template object wraps all of the boilerplate repetitive code. Then, this object delegates the persistence calls as a part of functionality in the template. In the Hibernate case, HibernateTemplate extracts all of the boilerplate code, such as obtaining a Session, performing transaction, and handing exceptions.

Sign up for a Packt account to see the rest of this article

Now that you've read a few articles, you might want to consider signing up for a Packt account. It takes a matter of seconds, will give you access to all the articles on PacktPub.com, and once you've signed up you'll be returned here to carry on reading your article.

Furthermore, you'll gain access to nine free ebooks, and be offered a free trial of PacktLib, Packt's online library. Simply enter your details here, or log in to your existing account.

Log in

...or register

Really Very Nice Article by
This is fantastic article on Hibernate & Spring ORm integration. Thanks for your excellent job! Well Done!!
Bravo ! by
Bonjour Ahmad, First, thank you for your beautiful article above. It was a very interesting read. I'm a Frenchman, a bit of a newbie in Hibernate and got some good value from your explanations. I saw your books are in Farsi, which means the experts in Hibernate all are in Teheran ? :-) I'm currently writing my first Dao layer, with a generic, but it seems that I should use the Spring class HibernateDaoSupport as you advise. I shall try to reshape my Dao with it. Kind Regards, Stephane, Aix-en-Provence, France mittiprovence@yahoo.se

Post new comment

Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Sort A-Z