Integrating Spring Framework with Hibernate ORM Framework: Part 2

Exclusive offer: get 50% off this eBook here
Spring Persistence with Hibernate

Spring Persistence with Hibernate — Save 50%

Build robust and reliable persistence solutions for your enterprise Java application

$29.99    $15.00
by Ahmad Seddighi | November 2009 | Java Open Source

Read Part One of Integrating Spring Framework with Hibernate ORM Framework here.

Configuring Hibernate in a Spring context

Spring provides the LocalSessionFactoryBean class as a factory for a SessionFactory object. The LocalSessionFactoryBean object is configured as a bean inside the IoC container, with either a local JDBC DataSource or a shared DataSource from JNDI.

The local JDBC DataSource can be configured in turn as an object of org.apache.commons.dbcp.BasicDataSource in the Spring context:

<bean id="dataSource" 
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost/hiberdb</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>

In this case, the org.apache.commons.dbcp.BasicDataSource (the Jakarta Commons Database Connection Pool) must be in the application classpath.

Similarly, a shared DataSource can be configured as an object of org.springframework.jndi.JndiObjectFactoryBean. This is the recommended way, which is used when the connection pool is managed by the application server. Here is the way to configure it:

<bean id="dataSource" 
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/HiberDB</value>
</property>
</bean>

When the DataSource is configured, you can configure the LocalSessionFactoryBean instance upon the configured DataSource as follows:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
...
</bean>

Alternatively, you may set up the SessionFactory object as a server-side resource object in the Spring context. This object is linked in as a JNDI resource in the JEE environment to be shared with multiple applications. In this case, you need to use JndiObjectFactoryBean instead of LocalSessionFactoryBean:

<bean id="sessionFactory" 
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/hiberDBSessionFactory</value>
</property>
</bean>

JndiObjectFactoryBean is another factory bean for looking up any JNDI resource.

When you use JndiObjectFactoryBean to obtain a preconfigured SessionFactory object, the SessionFactory object should already be registered as a JNDI resource. For this purpose, you may run a server-specific class which creates a SessionFactory object and registers it as a JNDI resource.

LocalSessionFactoryBean uses three properties: datasource, mappingResources, and hibernateProperties. These properties are as follows:

  • datasource refers to a JDBC DataSource object that is already defined as another bean inside the container.
  • mappingResources specifies the Hibernate mapping files located in the application classpath.
  • hibernateProperties determines the Hibernate configuration settings.

We have the sessionFactory object configured as follows:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>com/packtpub/springhibernate/ch13/Student.hbm.xml</value>
<value>com/packtpub/springhibernate/ch13/Teacher.hbm.xml</value>
<value>com/packtpub/springhibernate/ch13/Course.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.max_fetch_depth">2</prop>
</props>
</property>
</bean>

The mappingResources property loads mapping definitions in the classpath. You may use mappingJarLocations, or mappingDirectoryLocations to load them from a JAR file, or from any directory of the file system, respectively.

It is still possible to configure Hibernate with hibernate.cfg.xml, instead of configuring Hibernate as just shown. To do so, configure sessionFactory with the configLocation property, as follows:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="configLocation">
<value>/conf/hibernate.cfg.xml</value>
</property>
</bean>

Note that hibernate.cfg.xml specifies the Hibernate mapping definitions in addition to the other Hibernate properties.

When the SessionFactory object is configured, you can configure DAO implementations as beans in the Spring context. These DAO beans are the objects which are looked up from the Spring IoC container and consumed by the business layer. Here is an example of DAO configuration:

<bean id="studentDao" 
class="com.packtpub.springhibernate.ch13.HibernateStudentDao">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>

This is the DAO configuration for a DAO class that extends HibernateDaoSupport, or directly uses a SessionFactory property. When the DAO class has a HibernateTemplate property, configure the DAO instance as follows:

<bean id="studentDao" 
class="com.packtpub.springhibernate.ch13.HibernateStudentDao">
<property name="hibernateTemplate">
<bean
class="org.springframework.orm.hibernate3.HibernateTemplate">
<constructor-arg>
<ref local="sessionFactory"/>
</constructor-arg>
</bean>
</property>
</bean>

According to the preceding declaration, the HibernateStudentDao class has a hibernateTemplate property that is configured via the IoC container, to be initialized through constructor injection and a SessionFactory instance as a constructor argument.

Now, any client of the DAO implementation can look up the Spring context to obtain the DAO instance. The following code shows a simple class that creates a Spring application context, and then looks up the DAO object from the Spring IoC container:

package com.packtpub.springhibernate.ch13;

public class DaoClient {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"com/packtpub/springhibernate/ch13/applicationContext.xml");
StudentDao stdDao = (StudentDao)ctx.getBean("studentDao");
Student std = new Student();

//set std properties

//save std
stdDao.saveStudent(std);
}
}
Spring Persistence with Hibernate Build robust and reliable persistence solutions for your enterprise Java application
Published: November 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Spring transaction management

One reason to integrate Hibernate with Spring is transaction management. Spring provides a transaction abstraction layer over the Hibernate transaction API, and enables persistent operations to participate in global transactions. Moreover, Spring provides declarative transaction demarcation, which produces more readable and maintainable Java code. The declarative approach lets us change the transaction strategy easily, without changing the code.

The Spring transaction demarcation API has two classes for working with Hibernate applications:

  • org.springframework.transaction.support.TransactionTemplate for a programmatic approach.
  • org.springframework.transaction.interceptor.TransactionProxyFactoryBean for a declarative approach.

Behind this API, you may use one of Spring's two transaction managers:

  • org.springframework.orm.hibernate3.HibernateTransactionManager: Use this when the application involves a single data source and Hibernate alone is needed. This covers local transactions executed on a single SessionFactory. This manager is commonly used, since most Hibernate applications work with a single database.
  • org.springframework.transaction.jta.JtaTransactionManager: This is Spring's global JTA transaction manager. Use it when the application participates in global transactions in a Java EE environment, in which multiple SessionFactory methods are involved, and transactions are scattered over them.

Note that we can develop DAO classes that are not involved in transaction management. This is an advantage Spring provides for the application, so that all DAO classes work with transactional Session objects provided behind the scenes by the Spring IoC container.

You configure Spring's transactions by setting up the transaction-manager instance as a bean inside the IoC container. The bean configuration depends on which transaction strategy you are using: local or global.

Lets look at the transaction configuration in detail.

Local transactions

When the application uses only a single data source (a single SessionFactory in Hibernate), you can define the transaction manager as an instance of HibernateTransactionManager as follows:

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

Then, define DAO and Service beans, respectively, as instances of the DAO and service classes. Here is an example:

<bean id="persistenceService" 
class="com.packtpub.springhibernate.ch13.PersistenceService">
<property name="studentDao">
<ref bean="studentDao"/>
</property>
</bean>
<bean id="studentDao"
class="com.packtpub.springhibernate.ch13.HibernateStudentDao">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

Finally, the DAO instances are wrapped in a proxy transaction. Transactions are cross-cutting concerns that are not dedicated to the function of a particular method. Instead, they are scattered over many persistence methods. With Spring, DAO functionality can be split into two modules:

  • DAO implementations, which perform persistence operations.
  • Transaction advice, which defines how persistence operations are performed in transactions.

Modularizing DAO implementations to carry out persistence operations, and not transaction management, avoids boilerplate transaction-management code in every persistence method. To apply transaction advice to the target methods in the DAO implementations, we need proxy objects.

Each proxy is an object that intermediates between two other objects (a calling object and an invoked object), and applies a concern (a transaction in our case) to the object invocation. Actually, the business layer always works with instances of proxies instead of service objects. Here is an example of the transaction proxy definition:

<bean 
id="studentDao" class="org.springframework.transaction.
interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="persistenceService"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

The TransactionProxyFactoryBean object is configured with three properties:

  • transactionManager, declared as an individual bean, is an object which provides an abstraction API between the application code and Hibernate transaction API.
  • target represents the object to which the transaction concern must be applied.
  • transactionAttributes defines how to select the transactional methods. For instance, save* selects all methods of the target object that start with the save word.

In our example, PROPAGATION_REQUIRED and readOnly specify, respectively, how multiple transactions participate, and whether the transaction is allowed to only read the data.

Global transactions

You can configure Spring to use global transactions for synchronizing persistent operations that are performed in a Java EE environment across multiple data sources. The configuration process is similar to configuring a local transaction, but you need to define multiple data sources, as well as multiple SessionFactory and DAOs.

The transaction-manager object is now defined as an instance of JtaTransactionManager, instead of HibernateTransactionManager. Here is an example:

<beans>
<!-- the datasource1 declartion, registered to node ds1 on the
JNDI tree-->
<bean id="datasource1"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/ds1</value>
</property>
</bean>

<bean id="datasource2" class="org.springframework.jndi.
JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/ds2</value>
</property>
</bean>

<!-- the sessionFactory1 declaration, which uses datasource1-->
<bean id="sessionFactory1"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>Student.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource1"/>
</property>
</bean>

<!-- the sessionFactory2 declartion, which uses datasource2-->
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>Teacher.hbm.xml</value>
<value>Course.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource2"/>
</property>
</bean>

<!-- TransactionManager declaration -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>

<!-- A DAO configuration with the sessionFactory1-->
<bean id="studentDao"
class="com.packtpub.springhibernate.ch13.HibernateStudentDao">
<property name="sessionFactory">
<ref bean="sessionFactory1"/>
</property>
</bean>

<!-- A DAO configuration with the sessionFactory2-->
<bean id="teacherDao"
class="com.packtpub.springhibernate.ch13.HibernateTeacherDao">
<property name="sessionFactory">
<ref bean="sessionFactory2"/>
</property>
</bean>

<!-- A service instance configuration which reside in
the business layer -->
<!-- and works with both StudentDao and TeacherDao instances-->
<bean id="persistenceServiceTarget"
class="com.packtpub.springhibernate.ch13.PersistenceService">
<property name="studentDao">
<ref bean="studentDao"/>
</property>
<property name="teacherDao">
<ref bean="teacherDao"/>
</property>
</bean>

<!-- A proxy configuration, which applies the transactions on
the DAO methods-->
<bean
id="persistenceService"
class="org.springframework.transaction.interceptor.
TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="persistenceServiceTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

</beans>

Alternatively, you can configure the transaction manager as a bean of type JndiObjectFactoryBean in the IoC container. JndiObjectFactoryBean is a factory bean which obtains the transaction-manager object by looking up a JNDI resource. If you choose this strategy, the SessionFactory configuration changes as follows:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="jtaTransactionManager">
<ref bean="transactionManager"/>
</property>
<property name="mappingResources">
<list>
<value>com/packtpub/springhibernate/ch13/Student.hbm.xml</value>
<value>com/packtpub/springhibernate/ch13/Teacher.hbm.xml</value>
<value>com/packtpub/springhibernate/ch13/Course.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
</props>
</property>
</bean>

You must also configure a transaction-manager object:

<bean id="transactionManager"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/mytm</value>
</property>
</bean>

In this way, we configured transactionManager as a bean produced by JndiObjectFactoryBean. This factory bean returns transaction-manager objects by looking up a server-specific JNDI location.

Summary

In this article, you learned about the Data Access Object (DAO) pattern. This pattern allows all interaction with the data tier to be done through specific classes, called DAO classes. According to this pattern, a DAO interface is defined to correspond to each DAO class, defining all persistent operations that the business layer needs. The main goal is to decouple the business layer from the data layer. DAO interfaces are the only references that the business layer uses to perform persistent operations. At this point, Spring is configured to instantiate these references with the actual implementations at runtime.

You can integrate Hibernate with Spring to simplify DAO implementation. Spring provides a transaction abstraction layer on the local transaction API provided by Hibernate, and allows declarative transaction demarcation. Moreover, it converts HibernateException into Spring's generic DataAccessException hierarchy, and allows the use of IoC in the data tier.

Spring supports DAO implementation with two helper classes: org.springframework.orm.hibernate3.HibernateTemplate and org.springframework.orm.hibernate3.support.HibernateDaoSupport. All DAO classes extend HibernateDaoSupport and use HibernateTemplate to perform persistent operations. Spring provides org.springframework.orm.hibernate3.LocalSessionFactoryBean as a factory bean to configure and set up a SessionFactory object in an IoC-style manner. For transaction management, Spring provides org.springframework.orm.hibernate3.HibernateTransactionManager and org.springframework.transaction.jta.JtaTransactionManager for managing local and global transactions, respectively. Moreover, Spring provides org.springframework.transaction.interceptor.TransactionProxyFactoryBean, which acts as a proxy to apply transaction concerns to persistent operations.

If you have read this article you may be interested to view :

 

Spring Persistence with Hibernate Build robust and reliable persistence solutions for your enterprise Java application
Published: November 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Ahmad Seddighi

Ahmad Reza Seddighi is an author, speaker, and consultant in architecting and developing enterprise software systems. He is an IT graduate of the University of Isfahan, Iran, and has ten years of experience in software development. Currently, he lives in Tehran, where he works with a number of small but growing IT companies. He is also the author of three other books: Core Java Programming, Java Web Development, and Open Source J2EE Development, all in Farsi.

Books From Packt


JSF 1.2 Components
JSF 1.2 Components

JBoss RichFaces 3.3
JBoss RichFaces 3.3

Papervision3D Essentials
Papervision3D Essentials

RESTful Java Web Services
RESTful Java Web Services

jQuery 1.3 with PHP
jQuery 1.3 with PHP

Tomcat 6 Developer's Guide
Tomcat 6 Developer's Guide

JBoss AS 5 Development
JBoss AS 5 Development

Pentaho Reporting 3.5 for Java Developers
Pentaho Reporting 3.5 for Java Developers


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
u
t
U
q
s
e
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
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