When using an ORM framework on its own, you have to configure its resource factory with its API. For Hibernate and JPA, you have to build a session factory and an entity manager factory from the native Hibernate API and JPA.
You have no choice but to manage these objects manually, without Spring’s support.
Spring provides several factory beans for you to create a Hibernate session factory or a JPA entity manager factory as a singleton bean in the IoC container. These factories can be shared between multiple beans via dependency injection. Moreover, this allows the session factory and the entity manager factory to integrate with other Spring data access facilities, such as data sources and transaction managers.
In this tutorial we will see how to persist object using Hibernate 4 in a Spring 3.1 based web-application. This simple web app manages a single entity Person with the following DDL:
CREATE TABLE person ( pid int(11) NOT NULL AUTO_INCREMENT, firstname varchar(255) DEFAULT NULL, lastname varchar(255) DEFAULT NULL, PRIMARY KEY (pid) )
Ingredients
- Spring 3.1.1
- Hibernate 4.1.3
- MySQL 5.5
- Apache DBCP Commons Library
1 The POM file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.madbit.hibernate</groupId> <artifactId>spring-hibernate4</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>3.1.1.RELEASE</spring.version> </properties> <dependencies> <!-- Spring framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <!-- Used for Hibernate4 LocalSessionFactoryBean --> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <!-- AOP dependency --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <!-- Persistence Management --> <dependency> <!-- Apache BasicDataSource --> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <!-- MySQL database driver --> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.20</version> </dependency> <dependency> <!-- Hibernate --> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.1.3.Final</version> </dependency> </dependencies> </project>
2 Entity class
With hibernate an entity class it’s a POJO class with JPA2 annotation. The Person.java class that represents our entity “person” is the following:
package org.madbit.hibernate.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="person") public class Person { @Id @GeneratedValue(strategy=GenerationType.AUTO) private int pid; private String firstname; private String lastname; public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } }
3 The DAO
Now we can implement a simple DAO that allow to add new person in the database. Below the java code of MyDAO.java:
package org.madbit.hibernate.dao; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.madbit.hibernate.entity.Person; import org.springframework.transaction.annotation.Transactional; public class MyDAO { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Transactional(readOnly=false) public void addPerson(Person p) { Session session = sessionFactory.openSession(); session.save(p); session.close(); } }
4. Configuring Data access
4.1 Hibernate
Let’s create a bean configuration file for using Hibernate as the ORM framework datasource.xml in the classpath root (src/main/resources).
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mytest" /> <property name="username" value="root" /> <property name="password" value="" /> <property name="initialSize" value="2" /> <property name="maxActive" value="5" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="org.madbit.hibernate.entity" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> <bean id="myDAO" class="org.madbit.hibernate.dao.MyDAO" > <property name="sessionFactory" ref="sessionFactory" /> </bean>
4.2 Transaction Managment
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>
enable transaction managment on method annotated with
@Transactional
. Basically in that file are configured three beans, that is:
- Datasource
- Session-factory
- DAO
- Transaction Managment
4.2 Datasource
There are several data source implementations. Spring’s own data source implementations are mainly used for testing purposes. Database Connection Pooling Services (DBCP) module of the Apache Commons Library has several data source implementations that support connection pooling. We use BasicDataSource
allows you to specify the initial connection size and maximum active connections for the connection pool.
4.3 Session Factory
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
(class org.springframework.orm.hibernate4.LocalSessionFactoryBean
). It works with both annotation-based mapping and xml-based mapping. Subclass of Spring’s standard LocalSessionFactoryBean for Hibernate, supporting JDK 1.5+ annotation metadata for mappings. With property packagesToScan
it’s possible tell to Hibernate which package contains the JPA2 annotated classes representing the Database Entities. In alternative it’s possible specify the set of classes to be bound as a list, like this:
<property name="classesToBeBound"> <list> <value>org.madbit.hibernate.entity.Person</value> ... </list> </property>
This can be useful if you have JPA2 annotated classes in different package.
4.4 DAO configuration
The last bean declare the DAO passing the sessionFactory using setter injection.
5 AddPerson servlet
In order to insert new data we can implement a simple HTML page with a form containing all the Person’s attributes.
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Add user</title> </head> <body> <form action="addPerson" method="post"> First name: <input type="text" name="firstname"> Last name: <input type="text" name="lastname"> <input type="submit" value="Save"> </form> </body> </html>
The form action call the servlet addPerson. Below the servlet’s implementation:
package org.madbit.hibernate.web; import org.madbit.hibernate.dao.MyDAO; import org.madbit.hibernate.entity.Person; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class PersonController { @Autowired MyDAO myDAO; @RequestMapping(value="/addPerson", method=RequestMethod.POST) public String addPerson(@RequestParam("firstname") String firstname, @RequestParam("lastname") String lastname, Model model) { Person p = new Person(); p.setFirstname(firstname); p.setLastname(lastname); myDAO.addPerson(p); return "/result.jsp"; } }
As you can see, the servlet retrieve the form data from the HTTP request, create a new Person and insert it in the database throught the DAO. Using @Autowired
annotation you can get an already instantiated MyDAO Object from Spring IoC container. You have to enable register @Autowired
annotation, as following:
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
To configure the “person” (as declared in web.xml file) controller in Spring, you have to define a person-servlet.xml configuration file under /WEB-INF, as showed below:
<?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-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- Used for scan Controller Spring annotations --> <context:component-scan base-package="org.madbit.hibernate.web" /> </beans>
5 Web deployment descriptor
The final web.xml with the addPerson servlet declaration file is the following:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Spring Hibernate</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>person</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>person</servlet-name> <url-pattern>/person/*</url-pattern> </servlet-mapping> </web-app>
ApplicationContext file
<?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-3.1.xsd"> <import resource="classpath:datasource.xml"/> <!-- Register @Autowired annotation --> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> </beans>