As part of the Core-Spring course, we have a lab application that we use to show how to integrate Spring and JPA/Hibernate together. We have just upgraded it to Spring 3.1 / Hibernate 4.1, and thought we should share a few tips.
1) Maven Dependencies
The configuration sample below is based on Maven (but you can easily convert it to Gradle if needed). Inside your POM, you should specify the latest versions of Spring and Hibernate (you might need to declare more Spring dependencies depending on which Spring components you're using).
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.0.RELEASE</version>
<!-- will come with all needed Spring dependencies such as spring-core and spring-beans-->
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.9.Final</version>
<!-- will come with Hibernate core-->
</dependency>
The cglib dependency is not always needed. You will find more details on that at the end of this blog entry.
2.a) Spring configuration for Hibernate
Spring provides support for several versions of Hibernate, so you need to specify explicitly which version you're using.
With Hibernate 4:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
...
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
If you were to work with Hibernate 3, you would have instead:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
(the package path is different according to whether you wish to use Hibernate 3 or Hibernate 4)
When working with Hibernate, there are 2 common ways of writing your mapping: XML and annotations.
Spring-Hibernate 3 integration allows you to configure 2 kinds of SessionFactoryBean:
- LocalSessionFactoryBean for xml mapping only
- AnnotationSessionFactoryBean for xml mapping and/or Annotation-based mapping
With Spring 3.1 and Hibernate 4, things are now simpler: there is only one SessionFactoryBean called LocalSessionFactoryBean. It works with both annotation-based mapping and xml-based mapping.
If you followed those 2 steps carefully, you should have a running application already.
2.b) Spring configuration for JPA
As an alternative of using Hibernate directly, you can also use JPA as an abstraction layer on top of Hibernate. Here is an example:
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:jpa/config/schema.sql" />
</jdbc:embedded-database>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="jpaTest" />
<property name="packagesToScan">
<list>
<value>jpa/config</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
3) Do you need that CGLIB dependency?
The answer is likely to be a "yes". It is actually common that Spring would need it under the hood. Here are some examples:
- Java configuration (more info here)
- Adding features such as Transactional behavior, Security, Caching... to a Spring bean that does not implement an interface (more information here)
- When the @Transactional annotation is used inside a JUnit Test case (you usually do that so the database transaction can rollback at the end of each test case, see here for more details).
- ...
4) Java Configuration
Using Java Configuration with Spring is an interesting alternative to xml-based and annotation-based configuration. So how to work with Spring and Hibernate using Java configuration? A new class called LocalSessionFactoryBuilder makes things pretty easy.
@Bean
public SessionFactory sessionFactory() {
return new LocalSessionFactoryBuilder(dataSource())
.addAnnotatedClasses(Person.class, Account.class)
.buildSessionFactory();
}
LocalSessionFactoryBuilder subclasses Hibernate's own Configuration class, and as the name suggests, provides a convenient builder-style API for use within Spring @Configuration classes.
All the above code samples are available here:https://github.com/michaelisvy/hibernate-4-spring-3.1-samples