Spring + Hibernate Integration
Hibernate is a powerful technology for persisting data in any kind of Application. Spring, on the other hand is a dependency injection framework that supports IOC. The beauty of Spring is that it can integrates well with most of the prevailing popular technologies. In this article, we will discuss on how it is possible to integrate Spring with Hibernate. This article assumes that the reader has a basic understanding in both Spring and Hibernate Frameworks.
If you are new to Spring and Hibernate frameworks, please read the introduction articles on Spring and Hibernate before start reading this article Introduction to Spring Framework. This article will help you to understand the fundamentals of the Spring framework. In another article Introduction to Hibernate explains what is ORM framework and how to start writing the simple hibernate application.
Spring and Hibernate
As a pre-requisite, let us understand the need for such integration before we actually get into the integration between these two technologies. It is well known that Hibernate is a powerful ORM tool that lies between Application and Database. It enables Application to access data from any database in a platform-independent manner. There is no need for the Application to depend on the low-level JDBC details like managing connection, dealing with statements and result sets. All the necessary details for accessing a particular data source is easily configurable in Xml files. Another good thing is that Hibernate can be coupled well with both J2SE and J2EE Applications.
One of the problem with using Hibernate is that the client Application that accesses the database using Hibernate Framework has to depend on the Hibernate APIs like Configuration
, SessionFactory
and Session
. These objects will continue to get scattered across the code throughout the Application. Moreover, the Application code has to manually maintain and manage these objects. In the case of Spring, the business objects can be highly configurable with the help of IOC Container. In simple words, the state of an object can be externalized from the Application code. It means that now it is possible to use the Hibernate objects as Spring Beans and they can enjoy all the facilities that Spring provides.
Spring and Hibernate Integration Example
Instead of looking into the various Integration APIs that are available in the Spring Bundle, let us study and understand these APIs as we go through the sample code. The following sections cover the various steps involved in the Spring-Hiberante integration along with a detailed explanation.
Creating MySQL Database
The following sample application uses the MySql database for dealing with data. MySql database can be downloaded from http://dev.mysql.com/downloads/mysql/5.0.html#downloads. After installing the database, start the MySql client and create a test database by issuing the following command,
Create database samples;
Note that the character ';'
is the statement terminator for every command. Once the 'samples'
database is created, use the database for creating tables by using the command,
Use samples;
This uses the 'samples'
database for the current database session. It means that whatever operation we do, such as creating tables, will eventually affect the 'samples'
database. Now, let us create a sample table called 'employee'
which is having four fields namely id
, name
, age
and salary
. The following command creates the 'employee'
table in the 'samples'
database,
create table employee(id varchar(10), name varchar(20), age int(3), salary int(10));
Now an empty table (table with no records within it) is created.
The Employee class
Now let us create a class called Employee
for storing the data that are fetched from the employee
table. The class design is such that the column names for the table 'employee'
will be mapped as the variable names in the Java class with the appropriate data type. The complete code listing for the Employee class is as follows,
Employee.java
package javabeat.spring.hibernate; public class Employee { private String id; private String name; private int age; private double salary; public Employee() { } public String getId(){ return id; } public void setId(String id){ this.id = id; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public int getAge(){ return age; } public void setAge(int age){ this.age = age; } public double getSalary(){ return salary; } public void setSalary(double salary){ this.salary = salary; } public String toString(){ return "Id = " + id + ", Name = " + name + ", Age = " + age + ", Salary = " + salary; } }
Note that the toString()
method is overridden to give a meaningful display for the employee object.
Creating the Hibernate Mapping file
We have created 'employee'
table in the database and a corresponding Java class in the Application layer. However, we haven’t specified that the 'employee'
table should map to the Java class and the column names in the 'employee'
table should map to the Java variables in the Employee
class. This is where the Hibernate Mapping files comes into picture. Let us have a look at the Hibernate Mapping file,
employee.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "- //Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="javabeat.spring.hibernate.Employee" table="Employee"> <id name="id" column="Id"> <generator/> </id> <property name="name"> <column name="Name"/> </property> <property name="age"> <column name="Age"/> </property> <property name="salary"> <column name="Salary"/> </property> </class> </hibernate-mapping>
Note that the Mapping file is an Xml file and its name is employee.hbm.xml
. The portion of the string 'hbm'
in the mapping file stands for Hibernate Mapping File. Although it is not necessary to follow this convention, it will be easy to figure what type of xml file is this, just by looking at the extension. Xml conforms to a well-defined DTD, the hibernate-mappings-3.0.dtd
.
The root element for the mapping file is the hibernate-mapping
tag which can define one or more mappings, following which we have the class
tag which defines a mapping between the database table name and the Java class. The 'name'
attribute must point to a fully qualified Java class name whereas the table
attribte must point to the database table.
The next series of tags define the mapping definition of the column names against its Java variables counterparts. The 'id'
tag defines an identifier for a row and it is commonly used as a primary key column. The property
tag has an attribute called 'name'
which points to the Java variable name, following which is the name of the column in the database table to which it maps to.
Creating the Spring Configuration File
This section deals with configuring the various information needed for the Spring Framework. In Spring, all the business objects are configured in Xml file and the configured business objects are called Spring Beans. These Spring Beans are maintained by the IOC which is given to the Client Application upon request. Let us define a data source as follows,
spring-hibernate.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost/samples"/> <property name="username" value="root"/> <property name="password" value="pwForRoot"/> </bean> … </beans> …
The above bean defines a data-source of type 'org.apache.commons.dbcp.BasicDataSource'
. More importantly, it defines the various connection properties that are needed for accessing the database. For accessing the MySql database, we need MySql database driver which can be downloaded from http://dev.mysql.com/downloads/connector/j/5.1.html. The first property called driverClassName
should point to the class name of the MySql Database Driver. The second property url represents the URL string which is needed to connect to the MySql Database. The third and the fourth properties represent the database username
and the password
needed to open up a database session.
Now, let us define the second Spring Bean which is the SessionFactoryBean
. If you would have programmed in Hibernate, you will realize that SessionFactoryBean
is responsible for creating Session
objects through which Transaction
and Data accessing is done. Now the same SessionFactoryBean
has to be configured in Spring’s way as follows,
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3 .LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="mappingResources"> <list> <value>./resources/employee.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value>hibernate.dialect=org.hibernate.dialect .HSQLDialect</value> </property> </bean>
To make the SessionFactoryBean
to get properly configured, we have given two mandatory information. One is the data-source information which contains the details for accessing the database. This we have configured already in the previous step and have referred it here using the 'ref'
attribute in the 'property'
tag. The second one is a list of Mapping files which contains the mapping information between the database tables and the Java class names.
We have defined one such mapping file in section 2 and have referenced the same here with the 'list'
tag.
The 3rd important Spring Bean is the Hibernate Template. It provides a wrapper for low-level data accessing and manipulation. Precisely, it contains methods for inserting/delting/updating/finding data in the database. For the Hibernate Template to get configured, the only argument is the SessionFactoryBean
object as represented in the following section,
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> </bean>
The final Bean definition is the Dao class which is the client facing class. Since this class has to be defined in the Application level, it can contain any number of methods for wrapping data access to the Client. Since we know that it is the Hibernate Template class that interacts with the database, it will be ideal a refer an instance of Hibernate Template to the Dao class.
<bean id="employeeDao"> <property name="hibernateTemplate"> <ref bean="hibernateTemplate"/> </property> </bean>
Note that a reference is made to EmployeeDao
class which is discussed in the forthcoming section.
Defining the EmployeeDao class
As described earlier, this EmployeeDao
class can contain any number of methods that can be accessed by the clients. The design of this class can fall under two choices. One is this class can directly depend on the Hibernate Template object which is injected by the IOC for accessing the data. The second one is that it can make use of the Hibernate API for data accessing. The declaration of the class is as follows,
EmployeeDao.java
package javabeat.spring.hibernate; import java.sql.SQLException; import org.hibernate.HibernateException; import org.hibernate.Session; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; public class EmployeeDao { private HibernateTemplate hibernateTemplate; public void setHibernateTemplate(HibernateTemplate hibernateTemplate){ this.hibernateTemplate = hibernateTemplate; } public HibernateTemplate getHibernateTemplate(){ return hibernateTemplate; } public Employee getEmployee(final String id){ HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException,SQLException { return session.load(Employee.class, id); } }; return (Employee)hibernateTemplate.execute(callback); } public void saveOrUpdate(final Employee employee){ HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException,SQLException { session.saveOrUpdate(employee); return null; } }; hibernateTemplate.execute(callback); } }
This class makes use of Hibernate API (particularly the Session
object) for data accessing. To instruct Spring to access the Hibernate API, we have the put the piece of logic that makes use of the Hibernate API into a particular well defined method in a well known interface that Spring knows. It happens to be the HibernateCallback
interface with the method doInHibernate()
with an instance of Hibernate Session being passed.
Note that we have defined two methods; getEmployee()
and saveOrUpdate
in the EmployeeDao
class. And to make use of the Hibernate APIs, we have defined the code in the HibernateCallback.doInHibernate()
method and have informed Spring to execute this code by passing the interface reference to the HibernateTemplate.execute()
method.
The Example Client Application
SpringHibernateTest.java
package javabeat.spring.hibernate; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.orm.hibernate3.LocalSessionFactoryBean; public class SpringHibernateTest { public static void main(String[] args) { Resource resource = new FileSystemResource( "./src/resources/spring-hibernate.xml"); BeanFactory factory = new XmlBeanFactory(resource); Employee employee = new Employee(); employee.setId("123"); employee.setName("ABC"); employee.setAge(20); employee.setSalary(15000.00d); EmployeeDao employeeDao = (EmployeeDao)factory.getBean( "employeeDao"); employeeDao.saveOrUpdate(employee); Employee empResult = employeeDao.getEmployee("123"); System.out.println(empResult); } }
Finally, we come to the sample client Application for accessing the test data. The control goes like this. When the method BeanFactory.getBean("employeeDao")
is called, Spring finds the references made in the Bean definition of Employee
Dao Bean. It happens to be the Hibernate Template object. Then an attempt will be made to initialize the Hibernate Template object where it will see that a Session Factory Bean object is referenced. Then, while constructing the Session Factory Bean object, the data-source information will get resolved along with the database tables and the Java classes.
also read:
Summary
This article was aimed at discussing about Integration of Spring with Hibernate. It discussed the need for such an integration and also briefed about the benefits that it offers. Then, a very detailed step-by-step sample was given to clearly illustrate how the integration works. If you have any questions, please write it in the comments section. Similar to Spring and Hibernate integration example, you also read Spring and JSF integration.