Spring is one of the most used Java EE Framework and Hibernate is the most popular ORM framework. That’s why Spring Hibernate combination is used a lot in enterprise applications. Recently I have written a lot for Spring Tutorial and Hibernate Tutorial, so a post for spring hibernate integration was due for long time.
Today in this tutorial, we will use Spring 4 and integrate it with Hibernate 3 and then update the same project to use Hibernate 4. Since there are a lot of versions for Spring and Hibernate both and Spring ORM artifact supports both Hibernate 3 and Hibernate 4, it’s good that I list all the dependencies I have used in my project. Note that I have noticed that all spring and hibernate versions are not compatible, below versions have worked for me so I think they are compatible. If you are using some other versions and getting java.lang.NoClassDefFoundError
, then it means that they are not compatible. Mostly it’s because Hibernate classes are moved from one package to another causing this error. For example org.hibernate.engine.FilterDefinition
class is moved to org.hibernate.engine.spi.FilterDefinition
in latest hibernate versions.
I am using MySQL database for my project, so below setup.sql script will create the necessary table for this example.
CREATE TABLE `Person` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
commit;
Below image shows the final project structure, we will go through each of the components one by one.
We will first look into our pom.xml file for all the required dependencies and their versions.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringHibernateExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<!-- <hibernate.version>4.3.5.Final</hibernate.version> -->
<hibernate.version>3.6.9.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring ORM support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
Important Dependencies for Spring and Hibernate Integration Project are:
We can use Hibernate XML based mapping as well as JPA annotation based mapping. Here I am using JPA annotations for mapping because hibernate provides JPA implementation.
package com.journaldev.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity bean with JPA annotations
* Hibernate provides JPA implementation
* @author pankaj
*
*/
@Entity
@Table(name="Person")
public class Person {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String country;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
We will implement two methods in our DAO classes, first to save the Person object into table and second that will fetch all the records from the table and returns the list of Persons.
package com.journaldev.dao;
import java.util.List;
import com.journaldev.model.Person;
public interface PersonDAO {
public void save(Person p);
public List<Person> list();
}
Above DAO class implementation would be like below.
package com.journaldev.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.model.Person;
public class PersonDAOImpl implements PersonDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void save(Person p) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(p);
tx.commit();
session.close();
}
@SuppressWarnings("unchecked")
@Override
public List<Person> list() {
Session session = this.sessionFactory.openSession();
List<Person> personList = session.createQuery("from Person").list();
session.close();
return personList;
}
}
Notice that this is the only place where we are using Hibernate related classes. This pattern makes our implementation flexible and easy to migrate from one technology to another. For example, if we want to use iBatis ORM framework, all we need is to provide a DAO implementation for iBatis and then change the spring bean configuration file. In above example, I am using Hibernate session transaction management. But we can also use Spring declarative transaction management using @Transactional
annotation, read more at Spring Transaction Management.
Let’s first look at the spring bean configurations we need for Hibernate 3 integration, we will look into detail later on.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
<property name="username" value="pankaj" />
<property name="password" value="pankaj123" />
</bean>
<!-- Hibernate 3 XML SessionFactory Bean definition-->
<!-- <bean id="hibernate3SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean> -->
<!-- Hibernate 3 Annotation SessionFactory Bean definition-->
<bean id="hibernate3AnnotatedSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.journaldev.model.Person</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
</bean>
</beans>
There are two ways we can provide database connection details to Hibernate, first by passing everything in hibernateProperties
and second by creating a DataSource and then passing it to hibernate. I prefer the second approach, that’s why we have Apache Commons DBCP dependency to create a BasicDataSource
by setting database connection properties. For Spring and Hibernate 3 integration, Spring ORM provides two classes - org.springframework.orm.hibernate3.LocalSessionFactoryBean
when hibernate mappings are XML based and org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
for annotations based mapping. I have provided simple bean configuration of LocalSessionFactoryBean
in comments, if you are using XML based mappings. AnnotationSessionFactoryBean
extends LocalSessionFactoryBean
class, so it has all the basic properties for hibernate integration. The properties are self understood and mostly hibernate related, so I will not go into much detail for them. But if you are wondering from where hibernateProperties, annotatedClasses are coming, you need to look into the bean class source code. Notice the bean definition of personDAO, like I said earlier if we have to switch to some other ORM framework, we need to change the implementation class here and set any other properties we need.
Our setup is ready now, let’s write a simple program to test our application.
package com.journaldev.main;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.dao.PersonDAO;
import com.journaldev.model.Person;
public class SpringHibernateMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
Person person = new Person();
person.setName("Pankaj"); person.setCountry("India");
personDAO.save(person);
System.out.println("Person::"+person);
List<Person> list = personDAO.list();
for(Person p : list){
System.out.println("Person List::"+p);
}
//close resources
context.close();
}
}
When we execute above program, we get a lot of output related to Hibernate because I haven’t setup logging properly, but that’s out of scope of this tutorial. However we get following output generated by our program.
Person::id=3, name=Pankaj, country=India
Person List::id=1, name=Pankaj, country=India
Person List::id=2, name=Pankaj, country=India
Person List::id=3, name=Pankaj, country=India
Now let’s change our application to use Hibernate 4 instead of Hibernate 3. For this migration, we need to make only following configuration changes.
Change the hibernate version to 4.3.5.Final in the pom.xml file, as shown in comments above.
Change the spring bean configuration file, till now you must have figured out that Spring bean configuration file is the key for integration of spring and hibernate framework. Below spring bean configuration file will work for Spring 4 and Hibernate 4 versions.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
<property name="username" value="pankaj" />
<property name="password" value="pankaj123" />
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.journaldev.model.Person</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
</beans>
For hibernate 4, we need to use org.springframework.orm.hibernate4.LocalSessionFactoryBean
for SessionFactory bean, Spring ORM has merged both the classes for Hibernate 3 and there is a single class now, this is good to avoid confusion. All the other configurations are same as before.
That’s it, our project is successfully migrated to Hibernate 4, neat isn’t it. Just change the SpringHibernateMain
class to use spring4.xml
for beans configuration and it will work fine, you will get same output as before. You can download the final project from below link and play around with more configurations to learn more.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Line 1: FOR UPDATE clause allowed only for DECLARE CURSOR. 2019-11-27T20:16:55.570373660Z at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:259) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570377660Z at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1547) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570382560Z at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:548) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570386660Z at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:479) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570390660Z at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7344) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570396860Z at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2713) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570400860Z at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:224) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570404860Z at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:204) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570408660Z at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:401) ~[mssql-jdbc-6.4.0.jre8.jar!/:?] 2019-11-27T20:16:55.570412660Z at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:353) ~[c3p0-0.9.5.2.jar!/:0.9.5.2] 2019-11-27T20:16:55.570416460Z at org.hibernate.id.enhanced.TableStructure.executeQuery(TableStructure.java:216) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570420360Z at org.hibernate.id.enhanced.TableStructure.access$300(TableStructure.java:46) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570424360Z at org.hibernate.id.enhanced.TableStructure$1$1.execute(TableStructure.java:138) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570428260Z at org.hibernate.id.enhanced.TableStructure$1$1.execute(TableStructure.java:126) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570432260Z at org.hibernate.jdbc.WorkExecutor.executeReturningWork(WorkExecutor.java:55) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570436160Z at org.hibernate.jdbc.AbstractReturningWork.accept(AbstractReturningWork.java:34) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.570440060Z at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:57) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577071686Z at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:125) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577590688Z at org.hibernate.id.enhanced.PooledOptimizer.generate(PooledOptimizer.java:73) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577659489Z at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:482) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577677989Z at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577761689Z at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577788789Z at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577839189Z at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577861089Z at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577925490Z at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577943390Z at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:709) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577977090Z at org.hibernate.internal.SessionImpl.save(SessionImpl.java:701) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] 2019-11-27T20:16:55.577991790Z at org.hibernate.internal.SessionImpl.save(SessionImpl.java:696) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final]
- Naveen
Could any one please tell me how to run this project?
- giri
Hi, I am getting following error please help me: Exception in thread “main” org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean] for bean with name ‘hibernate3AnnotatedSessionFactory’ defined in class path resource [Spring.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1380) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:666) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:633) at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1489) at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1012) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:740) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85) at com.SpringMvcHibernate.EmployeeMain.main(EmployeeMain.java:13) Caused by: java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at org.springframework.util.ClassUtils.forName(ClassUtils.java:274) at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:437) at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1428) at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1372) … 10 more
- Gayatri
why web.xml is not required in this example?
- shivani
Hi, I’m new to Spring. In the Main function there’s this line: PersonDAO personDAO = context.getBean(PersonDAO.class); Is this the same as: PersonDAO personDAO = context.getBean(“personDAO”); ? Thanks in advance for your reply.
- Jam
Just “PERSON”! Not “Person” table name. When I changed it, all stay to work) thx for guide
- Ilya
Hello, i have one question, first of all i want to apoligize to you for my bad english. doesn’t occur SessionFactory for each dao object when we wire it with xml bean approach? does it need to create once if thats right? I hope i could express myself.
- Samet
Getting java.lang.IllegalArgumentException at personDAO.save(person) line in springhibernatemail class
- vishal
Nice tutorial! thanks…
- sumit
Thank you so much
- Akouri ammar