using JPA 2.x with spring 3.x transactions

This page demonstrates how to use JPA EntityManager within a Spring Transaction using HSQLDB a Java in memory database. We will use a Spring DataManager responsible for database interaction, Spring service class for transaction management.

This is a update for a blog post I written back in 2010. That post dealt with the same topic using plain JdbcTemplate.


  • Spring Pure Annotation based configuration (ZERO XML files) with an exception of the pom.xml file
  • Java JPA


Based on the default behavior, when the application throws a run time exception any method that is defined to be transactional issues a roll-back on whatever resource is currently participating in the transaction. To define a method as transactional just put an @Transactional annotation before it.

Full downloadable source for this page is available here. Corrections and enhancements are welcome, fork, change and push back to GitHub.


  • Java 8


The following example will demonstrate the transaction capabilities of the spring framework. Consider it a very basic “hello world” program for transactional code.

Create the pom.xml

vi 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">
		<pluginRepository> <!-- Ignore this repository. Its only used for document publication. -->


			<plugin> <!-- Ignore this plugin. Its only used for document publication. -->


The following class uses Spring Annotation based configuration that sets up the data source and transaction manager.

vi src/main/java/com/test/SpringConfig.java

package com.test;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

public class SpringConfig {

	public DataSource getDataSource() {
		DriverManagerDataSource dm = new DriverManagerDataSource();
		// change the "/tmp" to be another location on your system.
		return dm;

	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
		em.setPackagesToScan(new String[] { "com.test" });
		JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		return em;

	public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		return transactionManager;

	public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
		return new PersistenceExceptionTranslationPostProcessor();

	Properties additionalProperties() {
		Properties properties = new Properties();
		properties.setProperty("hibernate.flushMode", "FLUSH_AUTO");
		properties.setProperty("hibernate.hbm2ddl.auto", "update");
		properties.setProperty("hibernate.show_sql", "true");
		return properties;

The following is just an interface.

vi src/main/java/com/test/TestTransactionDataManager.java

package com.test;

public interface TestTransactionDataManager {
	public abstract Number writeData(String data);

vi src/main/java/com/test/TestTransactionDataManagerImpl.java

package com.test;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

 * This data manager is used to test the transactional capabilities
 * of the spring framework. The code below is not marked as transactional
 * however it participates in one when called from a transactional method.
public class TestTransactionDataManagerImpl implements TestTransactionDataManager {

	private EntityManager em;

	 * Responsible for writing data to a transactional resource.
	 * @param data
	public Number writeData(String data) {
		DBRecord record = new DBRecord();
    	return record.getId();

Just an interface…

vi src/main/java/com/test/TestTransactionModel.java

package com.test;

public interface TestTransactionModel {
	void writeDataWithOutTx(String message);
	void writeDataWithMultipleCalls(String message);
	void writeDataWithTx(String message);
	void writeDataWithTxSuccess();

This is our Model class. The model layer is a natural place to define unit of work. Model methods are called from “control layer” in the MVC architecture. (Struts actions, SpringMVC Command, or Servlets) THERE SHOULD BE AT MOST ONE call to a transaction enabled model method to get a the “unit of work” behavior. Otherwise if you have more than one call to these methods and one succeeds and the other fails you will not get the “unit of work” behavior. Please keep this in mind… Only one call to a transactional method from the “control layer”.

vi src/main/java/com/test/TestTransactionModelImpl.java

package com.test;

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

public class TestTransactionModelImpl implements TestTransactionModel {

	private TestTransactionDataManager testTransactionDataManager;
	public void writeDataWithTxSuccess() {
		testTransactionDataManager.writeData("Writing data within a transactional method. You WILL see this record.");

	public void writeDataWithOutTx(String message) {
		testTransactionDataManager.writeData("Writing data within a NON transactional method. You WILL NOT see this record.");

	 * This method will throw a runtime exception and the data will be rolled
	 * back.
	@Transactional  // remember @Transaction for public methods only!
	public void writeDataWithTx(String message) {
		if(message == null) {
			message = "Writing data within a transactional method with an exception. You will NOT see this record.";
		Number number = testTransactionDataManager.writeData(message);
		System.out.println("wrote item: " + number);
		throw new RuntimeException();

	 * This method tests the capability of calling another method that is
	 * declared to be transactional where the second method throws an exception
	 * but this method still commits. This is important to know that calling nested
	 * transactional methods will not result in a commit.
	public void writeDataWithMultipleCalls(String message) {
		String msg = "Suppressing runtimeexception and committing anyway you will see this record.";
		try {
		} catch(RuntimeException ex) {

The following is the JPA Entity we will be writing to the database.
vi src/main/java/com/test/DBRecord.java

package com.test;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

public class DBRecord {
	private Integer id;
	private String data;	
	public Integer getId() {
		return id;
	public void setId(Integer id) {
		this.id = id;
	public String getData() {
		return data;
	public void setData(String data) {
		this.data = data;
	public String toString() {
		return "DBRecord [id=" + id + ", data=" + data + "]";

The App.java JUnit Test doIt() method will call methods on the model layer.

vi src/test/java/com/test/App.java

package com.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {
//	private ApplicationContext context = new ClassPathXmlApplicationContext("com/test/applicationContext.xml");
	static private ApplicationContext context = null;
	static {
		context = new AnnotationConfigApplicationContext(com.test.SpringConfig.class);
	public void doIt() {
		TestTransactionModel model = (TestTransactionModel) context.getBean("testTransactionModel");
		try {
		} catch(Exception ex) {
		try {
		} catch (RuntimeException ex) { // do nothing

		try {
		} catch (RuntimeException ex) { // do nothing

		try {
		} catch (RuntimeException rex) { // do nothing

	public App() {



The results get saved to the HSQLDB database location that is specified in the SpringConfig.java file. It defaults to a file in the /tmp dir. Open the .script file and you will find the data saved to the table towards the bottom.


0 Responses to “using JPA 2.x with spring 3.x transactions”

  1. Leave a Comment

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 77 other followers

February 2016
« Dec   Mar »

Blog Stats

  • 795,599 hits

%d bloggers like this: