Spring + JPA + Hibernate example

27 December 2013
By Gonçalo Marques
In this tutorial we will configure Spring with JPA using Hibernate as our JPA implementation.

Introduction

Spring framework supports the persistence layer to be fully implemented through JPA. In this article we will see how to configure the Spring needed components to perform persistence over standard JPA, namely the Persistence Unit, the Entity Manager factory and the Transaction Manager. A fully working stand-alone Spring application is provided as a downloadable sample.

This tutorial considers the following environment:

  1. Ubuntu 12.04
  2. JDK 1.7.0.21
  3. Spring 3.2.5
  4. Hibernate 4.1.9

The following Maven dependencies are required:

Required Maven dependencies

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <spring.version>3.2.5.RELEASE</spring.version>
  <hibernate.version>4.1.9.Final</hibernate.version>
</properties>

<dependencies>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>${hibernate.version}</version>
  </dependency>

  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>${hibernate.version}</version>
  </dependency>

  <dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.2.2</version>
  </dependency>
  
</dependencies>

The JPA Entity

We will start the example by defining a simple JPA Entity that will be used through the article:

User.java

package com.byteslounge.spring.tx.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
@Table(name="USER")
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name="ID", nullable = false)
  private int id;
  
  @Column(name="USERNAME", nullable = false)
  private String username;
  
  @Column(name="NAME", nullable = false)
  private String name;
  
  public int getId() {
    return id;
  }
  
  public void setId(int id) {
    this.id = id;
  }

  public String getUsername() {
    return username;
  }
  
  public void setUsername(String username) {
    this.username = username;
  }
  
  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }
  
}

In this example we used MySQL as the RDBMS (database). The entity we just defined is mapped against the following table:

CREATE TABLE USER (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
USERNAME VARCHAR (32) NOT NULL,
NAME VARCHAR (64) NOT NULL,
UNIQUE (USERNAME)
);

The Spring service and DAO

Now we define a simple DAO that will be used to persist and read our User entities to and from the database. First the DAO interface and then the implementation:

UserDAO.java

package com.byteslounge.spring.tx.dao;

import java.util.List;

import com.byteslounge.spring.tx.model.User;

public interface UserDAO {

  void insertUser(User user);

  List<User> findAllUsers();

}



UserDAOImpl.java

package com.byteslounge.spring.tx.dao.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Repository;

import com.byteslounge.spring.tx.dao.UserDAO;
import com.byteslounge.spring.tx.model.User;

@Repository
public class UserDAOImpl implements UserDAO {

  @PersistenceContext
  private EntityManager entityManager;

  @Override
  public void insertUser(User user) {
    entityManager.persist(user);
  }

  @Override
  public List<User> findAllUsers() {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<User> cq = builder.createQuery(User.class);
    Root<User> root = cq.from(User.class);
    cq.select(root);
    return entityManager.createQuery(cq).getResultList();
  }

}

We just defined our sample DAO containing a couple of operations: One that inserts new users and another that fetches all users from the database.

The Entity Manager is injected through the regular JPA @PersistenceContext annotation.

Now we may proceed with the Spring service definition, first the service interface and then the implementation:

UserManager.java

package com.byteslounge.spring.tx.user;

import java.util.List;

import com.byteslounge.spring.tx.model.User;

public interface UserManager {

  void insertUser(User user);

  List<User> findAllUsers();

}



UserManagerImpl.java

package com.byteslounge.spring.tx.user.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.byteslounge.spring.tx.dao.UserDAO;
import com.byteslounge.spring.tx.model.User;
import com.byteslounge.spring.tx.user.UserManager;

@Service
public class UserManagerImpl implements UserManager {

  @Autowired
  private UserDAO userDAO;

  @Override
  @Transactional
  public void insertUser(User user) {
    userDAO.insertUser(user);
  }

  @Override
  public List<User> findAllUsers() {
    return userDAO.findAllUsers();
  }

}

We defined a Spring service that will provide both the insert and find operations to the service clients.

The DAO is injected into the service through the @Autowired annotation.

The insertUser method is annotated with @Transactional because we are actually modifying the information in the database, so we will need a transaction in order to commit our changes.

The Persistence Unit

As any JPA application we need to define a Persistence Unit. The definition goes into the persistence.xml file:

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
  http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

  <persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
    <class>com.byteslounge.spring.tx.model.User</class>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
    </properties>
  </persistence-unit>

</persistence>

We defined the classes (or entities) that will be managed by the persistence unit, in our case is a single entity: The User entity. If we had more entities we could define them individually using multiple class elements.

The persistence provider is defined as Hibernate (we are using Hibernate as the JPA implementation in this tutorial).

Since we are using MySQL as our database we defined the dialect to be used as the MySQL dialect.

Spring configuration

Finally we need to define Spring configuration itself:

spring.xml

<?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"
  xmlns:tx="http://www.springframework.org/schema/tx" 
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd 
  http://www.springframework.org/schema/tx 
  http://www.springframework.org/schema/tx/spring-tx.xsd">

  <tx:annotation-driven />

  <context:component-scan base-package="com.byteslounge.spring.tx.dao.impl" />
  <context:component-scan base-package="com.byteslounge.spring.tx.user.impl" />

  <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/TESTS" />
    <property name="username" value="user" />
    <property name="password" value="passwd" />
  </bean>

  <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="testPU" />
    <property name="dataSource" ref="dataSource" />
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
  </bean>

</beans>

We are configuring Spring to scan certain application packages for Spring managed components through the context:component-scan element (the configured packages are the ones that contain our Service and DAO).

We are also defining that transactions are configured through annotations by using tx:annotation-driven element. Remember that we demarcated the insertUser method to be transactional in our service by using @Transactional annotation.

We also configure a managed dataSource containing our database properties.

The Entity Manager Factory is configured to use the Persistence Unit we defined in the previous section together with the dataSource.

We also define a Transaction Manager that will be used by Spring to manage the required transactions (in this example the transactions are needed to commit the creation of new users).

Testing

Let's define a simple class in order to test our application:

Main.java

package com.byteslounge.spring.tx;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.byteslounge.spring.tx.model.User;
import com.byteslounge.spring.tx.user.UserManager;

public class Main {
  public static void main(String[] args) {

    ApplicationContext ctx = new ClassPathXmlApplicationContext(
        "spring.xml");

    UserManager userManager = (UserManager) ctx.getBean("userManagerImpl");

    List<User> list = userManager.findAllUsers();
    System.out.println("User count: " + list.size());

    User user = new User();
    user.setUsername("johndoe");
    user.setName("John Doe");
    userManager.insertUser(user);
    System.out.println("User inserted!");

    list = userManager.findAllUsers();
    System.out.println("User count: " + list.size());

  }

}

When we run the test class it will generate the following output:

User count: 0
User inserted!
User count: 1

The application source code is available for download at the end of this page.

Important note: You should have the database driver in the application classpath. The driver may be easily obtained through your database vendor website. In this article we used MySQL so we downloaded the driver from MySQL website. The driver is not provided with the sample application at the end of this page.

Download source code from this article

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: http://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: