Spring HibernateTempate Example

0

In this article, I will show you an example of spring’s HibernateTemplate. In Spring’s JdbcTemplate Example, we have seen how JdbcTemplate simplifies JDBC access. Just like JdbcTemplate, HibernateTemplate simplifies the Hibernate data access code. Hibernate access code can also be coded in plain Hibernate style based on org.hibernate.SessionFactory.getCurrentSession().

If you are using Hibernate 4.x, it is recommended to use the SessionFactory.getCurrentSession() which internally will return us the spring managed Session object.

We will use hibernate as our persistence framework. Our transaction consists of deleting all employees and then adding couple of new employees.

I will show you examples of:

  1. Hibernate transaction
  2. Transaction management using spring’s @Transactional attribute
  3. Transaction management using Hibernate API.

Except the first case, the last two methods will use spring managed session.

Hibernate Configuration

Our entity class is Employee. Define the object relational mapping.

employee.hbm.xml:

<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.javarticles.spring.hibernate">
	<class name="Employee" table="EMP">
		<id name="id" type="long" column="ID">
			<generator class="identity" />
		</id>
		<property name="name" type="string">
			<column name="NAME" length="100" not-null="true" />
		</property>
		<property name="contact" type="string">
			<column name="CONTACT" length="100" />
		</property>
	</class>
</hibernate-mapping>

Configure hibernate. We will use mysql database.

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">mnrpass</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hbm2ddl.auto">update</property>
    </session-factory>
</hibernate-configuration>

Hibernate Transaction

Since we are using hibernate, we need to define the following beans:

  1. DataSource
  2. SessionFactory bean. It will depend on the DataSource bean for the JDBC connection. You can also define the mapping resources here.

In our first example springHibernateExample, we will manage the Sessionourselves so we won’t define any TransactionManager here.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
		http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/test" />
		<property name="username" value="root" />
		<property name="password" value="mnrpass" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mappingResources">
			<list>
				<value>employee.hbm.xml</value>
			</list>
		</property>
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>
	<bean id="springHibernateExample" class="com.javarticles.spring.hibernate.SpringHibernateExample">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
</beans>

You can see in the below class, there is lot of boilerplate code involved to manage the Session object.

  1. We get the Session object from SessionFactory.
  2. Next, we start the Transaction
  3. We access the data using Session object
  4. Once we are done with the transaction, we commit it or rollback
  5. Finally, we close the Session object.

In the next example, I will use spring’s @Transactional attribute which will eliminate lot of boilerplate code meant to manage the transaction.

SpringHibernateExample:

package com.javarticles.spring.hibernate;

import java.io.IOException;
import java.util.List;

import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringHibernateExample {
    private SessionFactory sessionFactory;
    public static void main(String[] args) throws MappingException, IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringHibernateExample springHibernateExample = (SpringHibernateExample) context.getBean("springHibernateExample");
        springHibernateExample.execute();
    }
    
    public void execute() throws MappingException, IOException {
        Session session = sessionFactory.openSession();
        Transaction tx = session.getTransaction();
        try {
            tx.begin();
            Query query = session.createQuery("from Employee where name='Joe'");
            List empList = query.list();
            System.out.println("Employees found: " + empList.size());
            for(Employee emp: empList) {
                session.delete(emp);
                System.out.println("Deleted " + emp);
            }
            tx.commit();
            
            System.out.println("Create new employee Joe");
            tx = session.getTransaction();
            tx.begin();
            Employee emp = new Employee();
            emp.setName("Joe");
            session.saveOrUpdate(emp);
            tx.commit();
            
            query = session.createQuery("from Employee where name='Joe'");
            System.out.println("List all employees: " + query.list());
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;

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

Output:

Employees found: 1
Deleted Employee: Joe, id 50
Create new employee
List all employees: [Employee: Joe, id 52]

Data Access using Hibernate provided APIs

We will add @Transactional attribute at method level. This will automatically provide the method with a transaction so we don’t have to explicitly manage it. You also need to add an annotation processor so that spring can process the @Transactional attribute. It will intercept the method to create a transaction and then the method will be called.

<tx:annotation-driven/>

Since we are depending now on spring managed transaction, we also need to add a transaction manager.

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

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
		http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/test" />
		<property name="username" value="root" />
		<property name="password" value="mnrpass" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mappingResources">
			<list>
				<value>employee.hbm.xml</value>
			</list>
		</property>
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>
	<tx:annotation-driven/>
	<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	<bean id="springHibernateExample" class="com.javarticles.spring.hibernate.SpringHibernateExample">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean id="springHibernateSessionExample" class="com.javarticles.spring.hibernate.SpringTransactionUsingHibernateApiExample">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
</beans>

Even though we don’t have to bother about transaction now, we still are using hibernate provided APIs to access the data. If you are using Hibernate 4.x, it is recommended to use the SessionFactory.getCurrentSession() which internally will return us the spring managed Session object. Still using HibernateTemplate further simplifies the data access. In the next example, we will use HibernateTemplate.

SpringTransactionUsingHibernateApiExample:

package com.javarticles.spring.hibernate;

import java.io.IOException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;

public class SpringTransactionUsingHibernateApiExample {
    private SessionFactory sessionFactory;
    public static void main(String[] args) throws MappingException, IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringTransactionUsingHibernateApiExample springHibernateTemplateExample = (SpringTransactionUsingHibernateApiExample) context.getBean("springHibernateSessionExample");
        springHibernateTemplateExample.execute();
    }
    
    @Transactional(readOnly=true)
    public List<?> findEmployees() {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery("from Employee where name in (?, ?)");
        query.setParameter(0, "Joe");
        query.setParameter(1, "Sam");
        List<?> empList = query.list();
        System.out.println("Employees found: " + empList.size());
        return empList;
    }
    
    @Transactional(readOnly=false)
    public void deleteEmployees(List<?> empList) {
        if (!empList.isEmpty()) {
            Session session = sessionFactory.getCurrentSession();
            for (Object emp : empList) {
                session.delete(emp);
            }
            System.out.println("Employees deleted");
        }
    }
     
    @Transactional(readOnly=false)
    public void createEmployee(String name){
        System.out.println("Create new employee " + name);
        Session session = sessionFactory.getCurrentSession();
        Employee emp = new Employee();
        emp.setName(name);
        session.saveOrUpdate(emp);
        System.out.println("Employee created " + emp);
    }
    
    @Transactional(readOnly=false)
    public void saveEmployee(Employee emp){
        System.out.println("Create new employee " + emp);
        Session session = sessionFactory.getCurrentSession();
        session.save(emp);
        System.out.println("Employee created " + emp);        
    }
    
    @Transactional(readOnly=false)
    public void execute() {
        List<?> empList = findEmployees();
        deleteEmployees(empList);
        createEmployee("Joe");
        Employee empSam = new Employee();
        empSam.setName("Sam");
        saveEmployee(empSam);
        System.out.println("List of employees: " + findEmployees());
    }
    
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }    
}

Output:

Employees found: 2
Employees deleted
Create new employee Joe
Employee created Employee: Joe, id 55
Create new employee Employee: Sam, id 0
Employee created Employee: Sam, id 56
Employees found: 2
List of employees: [Employee: Joe, id 55, Employee: Sam, id 56]

Data Access using HibernateTemplate

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
		http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/test" />
		<property name="username" value="root" />
		<property name="password" value="mnrpass" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mappingResources">
			<list>
				<value>employee.hbm.xml</value>
			</list>
		</property>
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>
	<tx:annotation-driven/>
	<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	<bean id="springHibernateExample" class="com.javarticles.spring.hibernate.SpringHibernateExample">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean id="springHibernateSessionExample" class="com.javarticles.spring.hibernate.SpringTransactionUsingHibernateApiExample">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean id="springHibernateTemplateExample" class="com.javarticles.spring.hibernate.SpringHibernateTemplateExample">
		<property name="hibernateTemplate" ref="hibernateTemplate" />
	</bean>
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
</beans>

Spring’s HibernateTemplate provides an abstract layer over a Hibernate Session. It converts Hibernate-specific exceptions to one of the Spring’s unchecked data-access exception.
It also provides many convenience methods that help you in querying and persisting objects.
SpringHibernateTemplateExample:

package com.javarticles.spring.hibernate;

import java.io.IOException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.Session;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;

public class SpringHibernateTemplateExample {
    private HibernateTemplate hibernateTemplate;
    public static void main(String[] args) throws MappingException, IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringHibernateTemplateExample springHibernateTemplateExample = (SpringHibernateTemplateExample) context.getBean("springHibernateTemplateExample");
        springHibernateTemplateExample.execute();
    }
    
    @Transactional(readOnly=true)
    public List<?> findEmployees() {
        List<?> empList = hibernateTemplate.find("from Employee where name in (?, ?)", "Joe", "Sam");
        System.out.println("Employees found: " + empList.size());
        return empList;
    }
    
    @Transactional(readOnly=false)
    public void deleteEmployees(List<?> empList) {
        if (!empList.isEmpty()) {
            hibernateTemplate.deleteAll(empList);
            System.out.println("Employees deleted");
        }
    }
     
    @Transactional(readOnly=false)
    public void createEmployee(final String Name){
        System.out.println("Create new employee " + Name);
        Employee emp = hibernateTemplate.execute(new HibernateCallback() {

            public Employee doInHibernate(Session session) throws HibernateException {
                Employee emp = new Employee();
                emp.setName(Name);
                session.saveOrUpdate(emp);
                return emp;
            }
        });
        System.out.println("Employee created " + emp);
    }
    
    @Transactional(readOnly=false)
    public void saveEmployee(Employee emp){
        System.out.println("Create new employee " + emp);
        hibernateTemplate.save(emp);
        System.out.println("Employee created " + emp);        
    }
    
    @Transactional(readOnly=false)
    public void execute() {
        List<?> empList = findEmployees();
        deleteEmployees(empList);
        Employee empJoe = new Employee();
        createEmployee("Joe");
        Employee empSam = new Employee();
        empSam.setName("Sam");
        saveEmployee(empSam);
        System.out.println("List of employees: " + findEmployees());
    }
    
    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }    
}

Output:

Employees found: 2
Employees deleted
Create new employee Joe
Employee created Employee: Joe, id 57
Create new employee Employee: Sam, id 0
Employee created Employee: Sam, id 58
Employees found: 2
List of employees: [Employee: Joe, id 57, Employee: Sam, id 58]

Download source code

This article was about spring managed transactions and how we can use HibernateTemplate to further simplify the data access. You can download the source code here: springHibernateTemplateExample.zip

Share.

Comments are closed.