Spring 4 + Hibernate 5 + JPA 2 integration example

Posted on April 24, 2017


The Java Persistence API (a.k.a. JPA) is a Java specification for managing, persisting and accessing data between objects and relation database. Hibernate is an ORM (Object Relational Mapping) tool which implements JPA specification.

In this example, we will learn how to integrate the Spring with JPA, using the Hibernate as a persistence provider.

Tools and technologies used for this application are -

  • Spring 4.3.7.RELEASE
  • Hibernate 5.2.9.Final
  • JPA 2.1
  • MySQL Connector 6.0.5
  • MySQL Server 5.7.12
  • Eclipse Neon.3
  • Maven 3.3.9
  • JavaSE 1.8

Let us proceed to write a simple standalone application using Spring, Hibernate and JPA.

Project structure

Review the following maven project structure.

spring-hibernate-jpa.png

Refer this article to learn - How to create a maven project in eclipse.

Jar dependencies

Edit your pom.xml file and add Spring, Hibernate and MySQL dependencies as follows.

pom.xml

<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>com.boraji.tutorial.hibernate</groupId>
  <artifactId>spring-hibernate-jpa-example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-hibernate-jpa-tutorial</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- Spring Context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.7.RELEASE</version>
    </dependency>
    <!-- Spring ORM -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>4.3.7.RELEASE</version>
    </dependency>
    <!-- Mysql Connector -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.5</version>
    </dependency>
    <!-- Hibernate 5.2.9 Final -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.9.Final</version>
    </dependency>
    <!-- Apache Commons DBCP -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>2.1.1</version>
    </dependency>
  </dependencies>

  <build>
    <sourceDirectory>src/main/java</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

JPA Entity class

Create an @Entity class under com.boraji.tutorial.spring.entity package as follows.

Person.java

package com.boraji.tutorial.spring.entity;

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 = "PERSONS")
public class Person {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @Column(name = "FIRST_NAME")
   private String firstName;

   @Column(name = "LAST_NAME")
   private String lastName;

   @Column(name = "EMAIL")
   private String email;

   public Person() {}
   
   public Person(String firstName, String lastName, String email) {
      this.firstName = firstName;
      this.lastName = lastName;
      this.email = email;
   }

   // Getter and Setter methods
}

Data Access Object (DAO) class

Create @Repository classes under com.boraji.tutorial.spring.dao package as follows.

PersonDao.java

package com.boraji.tutorial.spring.dao;

import java.util.List;

import com.boraji.tutorial.spring.entity.Person;

public interface PersonDao {
   void add(Person person);
   List<Person> listPersons();
}

PersonDaoImp.java

package com.boraji.tutorial.spring.dao;

import java.util.List;

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

import org.springframework.stereotype.Repository;

import com.boraji.tutorial.spring.entity.Person;

/**
 * @author imssbora
 *
 */
@Repository
public class PersonDaoImp implements PersonDao {

   @PersistenceContext
   private EntityManager em;

   @Override
   public void add(Person person) {
      em.persist(person);
   }

   @Override
   public List<Person> listPersons() {
      CriteriaQuery<Person> criteriaQuery = em.getCriteriaBuilder().createQuery(Person.class);
      @SuppressWarnings("unused")
      Root<Person> root = criteriaQuery.from(Person.class);
      return em.createQuery(criteriaQuery).getResultList();
   }

}

The @PersistenceContext annotation is used to inject the EntityManager object into DOA classes.

 

Service class

Create @Service classes under com.boraji.tutorial.spring.service package as follows.

PersonService.java

package com.boraji.tutorial.spring.service;

import java.util.List;

import com.boraji.tutorial.spring.entity.Person;

public interface PersonService {
    void add(Person person);
    List<Person> listPersons();
}

PersonServiceImp.java

package com.boraji.tutorial.spring.service;

import java.util.List;

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

import com.boraji.tutorial.spring.dao.PersonDao;
import com.boraji.tutorial.spring.entity.Person;

/**
 * @author imssbora
 *
 */
@Service
public class PersonServiceImp implements PersonService {

   @Autowired
   private PersonDao userDao;

   @Transactional
   @Override
   public void add(Person person) {
      userDao.add(person);
   }

   @Transactional(readOnly = true)
   @Override
   public List<Person> listPersons() {
      return userDao.listPersons();
   }

}

persistence.xml file

Create a persistence.xml file under src/main/java/META-INF folder and write the following code in it.

persistence.xml

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
  version="2.1">

  <persistence-unit name="LOCAL_PERSISTENCE">
    <description> Spring Hibernate JPA Configuration Example</description>
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

    <properties>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/BORAJI" />
      <property name="javax.persistence.jdbc.user" value="root" />
      <property name="javax.persistence.jdbc.password" value="admin" />
      <property name="hibernate.show_sql" value="true" />
      <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>

  </persistence-unit>
</persistence>

This persistence.xml is used to configure the EntityManager inside an application server or standalone application. It contains the database (Connection URL, username, password etc.) and ORM related information. 

Spring configuration

Create @Configuration class under com.boraji.tutorial.spring.config package.

Annotate this configuration class with @EnableTransactionManagement annotation to enable transaction management capability.

AppConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @author imssbora
 *
 */
@Configuration
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.boraji.tutorial.spring.dao"),
      @ComponentScan("com.boraji.tutorial.spring.service") })
public class AppConfig {

   @Bean
   public LocalEntityManagerFactoryBean geEntityManagerFactoryBean() {
      LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
      factoryBean.setPersistenceUnitName("LOCAL_PERSISTENCE");
      return factoryBean;
   }

   @Bean
   public JpaTransactionManager geJpaTransactionManager() {
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(geEntityManagerFactoryBean().getObject());
      return transactionManager;
   }
}

 

Run application

Create a main class to test the above spring-hibernate-jpa configuration.

MainApp.java

package com.boraji.tutorial.spring;

import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.boraji.tutorial.spring.config.AppConfig;
import com.boraji.tutorial.spring.entity.Person;
import com.boraji.tutorial.spring.service.PersonService;

/**
 * @author imssbora
 *
 */
public class MainApp {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AppConfig.class);

      PersonService personService = context.getBean(PersonService.class);

      // Add Persons
      personService.add(new Person("Sunil", "Bora", "[email protected]"));
      personService.add(new Person("David", "Miller", "[email protected]"));
      personService.add(new Person("Sameer", "Singh", "[email protected]"));
      personService.add(new Person("Paul", "Smith", "[email protected]"));

      // Get Persons
      List<Person> persons = personService.listPersons();
      for (Person person : persons) {
         System.out.println("Id = "+person.getId());
         System.out.println("First Name = "+person.getFirstName());
         System.out.println("Last Name = "+person.getLastName());
         System.out.println("Email = "+person.getEmail());
         System.out.println();
      }

      context.close();
   }
}

Output

Hibernate: create table PERSONS (id bigint not null auto_increment, EMAIL varchar(255), FIRST_NAME varchar(255), LAST_NAME varchar(255), primary key (id)) engine=MyISAM
Hibernate: insert into PERSONS (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into PERSONS (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into PERSONS (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: insert into PERSONS (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
Hibernate: select person0_.id as id1_0_, person0_.EMAIL as EMAIL2_0_, person0_.FIRST_NAME as FIRST_NA3_0_, person0_.LAST_NAME as LAST_NAM4_0_ from PERSONS person0_
Id = 1
First Name = Sunil
Last Name = Bora
Email = [email protected]

Id = 2
First Name = David
Last Name = Miller
Email = [email protected]

Id = 3
First Name = Sameer
Last Name = Singh
Email = [email protected]

Id = 4
First Name = Paul
Last Name = Smith
Email = [email protected]
Download Sources