Hibernate 4 with Spring

1. Overview

This article will focus on setting up Hibernate 4 with Spring – we’ll look at how to configure Spring with Hibernate 4 using both Java and XML Configuration. Parts of this process are of course common to the Hibernate 3 article.

2. Maven

To add the Spring Persistence dependencies to the project pom.xml, please see the article focused on the Spring and Maven dependencies.

Continuing with Hibernate 4, the Maven dependencies are simple:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.6.Final</version>
</dependency>

Then, to enable Hibernate to use its proxy model, we need javassist as well:

<dependency>
   <groupId>org.javassist</groupId>
   <artifactId>javassist</artifactId>
   <version>3.18.2-GA</version>
</dependency>

And since we’re going to use MySQL for this tutorial, we’ll also need:

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.32</version>
   <scope>runtime</scope>
</dependency>

And finally, we are using a proper connection pool instead of the dev-only Spring implementation – the DriverManagerDataSource. We’re using here the Tomcat JDBC Connection Pool:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-dbcp</artifactId>
    <version>7.0.55</version>
</dependency>

3. Java Spring Configuration for Hibernate 4

To use Hibernate 4 in a project, a few things have changed on the configuration side when moving from a Hibernate 3 setup.

The main aspect that is different when upgrading from Hibernate 3 is the way to create the SessionFactory with Hibernate 4.

This is now done by using the LocalSessionFactoryBean from the hibernate4 package – which replaces the older AnnotationSessionFactoryBean from the hibernate3 package. The new FactoryBean has the same responsibility – it bootstraps the SessionFactory from annotation scanning. This is neccessary because, starting with Hibernate 3.6, the old AnnotationConfiguration was merged into Configuration and so the new Hibernate 4 LocalSessionFactoryBean is using this new Configuration mechanism.

It is also worth noting that, in Hibernate 4, the Configuration.buildSessionFactory method and mechanism have also been deprecated in favour of Configuration.buildSessionFactory(ServiceRegistry) – which the Spring LocalSessionFactoryBean is not yet using.

The Spring Java Configuration for Hibernate 4:

import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.google.common.base.Preconditions;

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-mysql.properties" })
@ComponentScan({ "org.baeldung.spring.persistence" })
public class PersistenceConfig {

   @Autowired
   private Environment env;

   @Bean
   public LocalSessionFactoryBean sessionFactory() {
      LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
      sessionFactory.setDataSource(restDataSource());
      sessionFactory.setPackagesToScan(new String[] { "org.baeldung.spring.persistence.model" });
      sessionFactory.setHibernateProperties(hibernateProperties());

      return sessionFactory;
   }

   @Bean
   public DataSource restDataSource() {
      BasicDataSource dataSource = new BasicDataSource();
      dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
      dataSource.setUrl(env.getProperty("jdbc.url"));
      dataSource.setUsername(env.getProperty("jdbc.user"));
      dataSource.setPassword(env.getProperty("jdbc.pass"));

      return dataSource;
   }

   @Bean
   @Autowired
   public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
      HibernateTransactionManager txManager = new HibernateTransactionManager();
      txManager.setSessionFactory(sessionFactory);

      return txManager;
   }

   @Bean
   public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
      return new PersistenceExceptionTranslationPostProcessor();
   }

   Properties hibernateProperties() {
      return new Properties() {
         {
            setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
            setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
            setProperty("hibernate.globally_quoted_identifiers", "true");
         }
      };
   }
}

4. XML Spring Configuration for Hibernate 4

Simillary, Hibernate 4 can be configured with XML as well:

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

   <context:property-placeholder location="classpath:persistence-mysql.properties" />

   <bean id="sessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="packagesToScan" value="org.baeldung.spring.persistence.model" />
      <property name="hibernateProperties">
         <props>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
         </props>
      </property>
   </bean>

   <bean id="dataSource" 
    class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.user}" />
      <property name="password" value="${jdbc.pass}" />
   </bean>

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

   <bean id="persistenceExceptionTranslationPostProcessor" 
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

</beans>

To bootstrap the XML into the Spring Context, we can use a simple Java Configuration file if the application is configured with Java configuration:

@Configuration
@EnableTransactionManagement
@ImportResource({ "classpath:hibernate4Config.xml" })
public class HibernateXmlConfig{
   //
}

Alternativelly we can simply provide the XML file to the Spring Context, if the overall configuration is purely XML.

For both types of configuration, the JDBC and Hibernate specific properties are stored in a properties file:

# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate_dev?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql

# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop

5. Spring, Hibernate and MySQL

The Drivers and Dialects supported by Hibernate have been extensively discussed for Hibernate 3 – and everything still applies for Hibernate 4 as well.

6. Usage

At this point, Hibernate 4 is fully configured with Spring and we can inject the raw Hibernate SessionFactory directly whenever we need to:

public abstract class BarHibernateDAO{

   @Autowired
   SessionFactory sessionFactory;

   ...

   protected Session getCurrentSession(){
      return sessionFactory.getCurrentSession();
   }
}

An important note here is that this is now the recommended way to use the Hibernate API – the older HibernateTemplate is no longer included in the new org.springframework.orm.hibernate4 package as it shouldn’t be used with Hibernate 4.

7. Conclusion

In this example, we configured Spring with Hiberate 4 – both with Java and XML configuration.

The implementation of this Spring Hibernate 4 Tutorial can be downloaded as a working sample project.

This is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Persistence on Google+ - you can follow me there:

>> GET THE EBOOKS <<
Get the eBooks and Learn to Build a Simple App
×
Build a Simple but Working App with Spring

,

  • pavan bangaram

    Excellent information. This might be useful for every Java candidate.. Than x.!

  • tony

    SessionFactory…..
    session is auto Close?

    • baeldung

      The question is far to general to know what you’re really asking. Please consider giving some more detail. An even better alternative is to create an github issue for the tutorial project – and I’ll take a look.
      Cheers,
      Eugen.

      • MK

        I believe what he is asking for is what happens with sessionFactory object. While you use plain java you usually invoke close() method on factory at the end of apllication or ContextListener.contextDestroyed() in web-app. Do spring hadle closing it internally or still you have to handle it manually?
        Any way if it’s what he’s asking or not could you answer me =)?

        • http://www.baeldung.com/ Eugen Paraschiv

          Hey MK – yes, Spring will take care of closing the session factory. If you look at the LocalSessionFactoryBean, you’ll notice that it is a DisposableBean, and the destroy method closes the factory.
          Cheers,
          Eugen.

  • xibaarinfo

    Hello, how to come accross multiple data base withe generic. I have trouble with the session factory.
    This is my error : No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: firstDatasSessionFactory,secondMasterSessionFactory:
    Thanks

  • arjun

    Hi
    I tried your example in JBOSS EAP 6.1 alpha , but I am getting this exception when I deploy it .

    java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreignKey()Ljavax/persistence/ForeignKey;

    Do you know why this is coming.

    Thanks

    • http://www.baeldung.com/ Eugen Paraschiv

      JBoss comes in with its own set of libraries, especially for JPA (more than a lightweight web server like Tomcat does), so you may end up with different binary versions of the standard JPA classes; you’ll first need to check these exact versions and then you’ll need to either align the two versions or check for other JBoss specific solutions.
      Cheers.
      Eugen.

  • http://www.klebermota.eti.br/ Kleber Mota

    Hi Eugen,
    one question: in the DAO classes, it was being Autowired the bean SessionFactory. Do I can do the same for DataSource? I am asking because I am developing an application with Spring Security and I have the idea to make this in my class SecurityConfig, but I get an error and my application don’t run. What I can do? Do you have any sugestion for me?
    Kleber Mota

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Kleber,
      The data source is a bean, so yes, you will be able to wire it in if you need to (why does your Security config need the data source?). Also – is this a public project – that would help me run it and see what the issue is.
      Cheers,
      Eugen.

  • ssssssssss

    is there a code download of this example?

    • http://www.baeldung.com/ Eugen Paraschiv

      Sure – the project is hosted on github – there’s a link at the end of the article. Cheers,
      Eugen.

  • JavaProgrammer

    It would be nice if you could have indicated where that Spring xml config file should be placed in the project. For example where it would be located if you would be using Maven project? I have tried to implement your solution but it doesn’t work because when I try to inject entitymanager it doesn’t find the configuration file and thus my entity manager is always null.

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey JavaProgrammer – that kind if details is readily available on github – you will find the link to the project at the end of the article. Cheers,
      Eugen.

  • Geoffrey Stanley

    Would you happen to know how to configure the XML to be able to use two difference data sources?

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Geoffrey – you’d simply be using the one that the session factory would be referencing. If you’d like to have 2 session factories as well – that’s perfectly fine – you’ll simply have to inject them by name in Spring, so that you can use either one. Hope that helps – cheers,
      Eugen.

      • Geoffrey Stanley

        Hello Eugen,
        Thank you for your reply. I’ve tried defining two different session factories in XML and I’m able to use the two different session factories when explicitly referencing one or the other in the code however, I can’t seem to figure out how to dynamically change from one or the other at run time.

        I’ve been using the @transaction() notation and it only seems to allow me to use one transaction manager at once.

        • http://www.baeldung.com/ Eugen Paraschiv

          So – it depends on what you’re trying to do – either use both of them at once, or switch between one and the other dynamically. It sounds like you’re trying to do the dynamic option – you can use profiles for that and switch based on whatever active profile you’re running with.

          • Geoffrey Stanley

            Hello, yes I’m trying to switch between them dynamically. The code I have written is as follows:

            @Autowired
            SessionFactory sessionFactory;

            @Transactional(“TransactionManager1″)
            public Session getSession1(){
            LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
            sessionFactory = bean.getObject();

            return sessionFactory.getCurrentSession();
            }

            @Transactional(“TransactionManager2″)
            public Session getSession2(){
            LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
            sessionFactory = bean.getObject();

            return sessionFactory.getCurrentSession();
            }

            However the problem is that I’m getting a null pointer exception at “return sessionFactory.getCurrentSession();” and I can’t seem to figure out why.

          • http://www.baeldung.com/ Eugen Paraschiv

            OK – there are a few possible causes for not having a current session open – can you point me towards a github project (or sample) replicating the issue? It’s going to help actually diagnose what’s happening – and also move the lenghty code samples out of these comments. Cheers,
            Eugen.

  • Craig

    Hey, I’m trying to use your example but with a com.microsoft.sqlserver.jdbc.SQLServerDriver but the sessionFactory that I have tried to autowire is null. There are no errors in the logs to explain it. Do you know why this could be?

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Craig – it can be any number of things – my suggestion is to reproduce it somewhere, such as a sample project on github – and I’d be happy to take a look. Cheers,
      Eugen.

  • Gaurav Dighe

    Hey,
    I am trying to use Spring 4 and Hibernate4 along with Spring-Data-JPA-1.5. Is everything the same as far as setting up and running the project or is it different?

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Gaurav, in order to use Spring Data JPA, you’ll have to set up JPA – so no, this configuration won’t work exactly as is; you can check out my intro to Spring Data JPA for the configuration. Cheers,
      Eugen.

  • Jason.H

    tks for ur post ! :D
    where did u configured the tomcat-dbcp for hibernate ? i can see it no where …

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Jason – it’s the BasicDataSource used in both configuration – that’s part of the tomcat-dbcp jar. Cheers,
      Eugen.