Transaction configuration with JPA and Spring 3.1

1. Overview

This tutorial will discuss the right way to configure Spring Transactions, use the @Transactional annotation and common pitfalls.

For a more in depth discussion on the core persistence configuration, check out the Spring with JPA tutorial.

There are two distinct ways to configure Transactions – annotations and AOP – each with their own advantages – we’re going to discuss the more common annotation config here.

2. Configure Transactions without XML

Spring 3.1 introduces the @EnableTransactionManagement annotation to be used in on @Configuration classes and enable transactional support:

public class PersistenceJPAConfig{

   public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){

   public PlatformTransactionManager transactionManager(){
      JpaTransactionManager transactionManager = new JpaTransactionManager();
       entityManagerFactoryBean().getObject() );
      return transactionManager;

3. Configure Transactions with XML

Before 3.1 or if Java is not an option, here is the XML configuration, using annotation-driven and the namespace support:

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="myEmf" />
<tx:annotation-driven transaction-manager="txManager" />

4. The @Transactional Annotation

With transactions configured, a bean can now be annotated with @Transactional either at the class or method level:

public class FooService {

The annotation supports further configuration as well:

  • the Propagation Type of the transaction
  • the Isolation Level of the transaction
  • a Timeout for the operation wrapped by the transaction
  • a readOnly flag – a hint for the persistence provider that the transaction should be read only
  • detailed Rollback configuration

5. Potential Pitfalls

5.1. Transactions and Proxies

At a high level, Spring creates proxies for all the classes annotated with @Transactional – either on the class or on any of the methods. The proxy allows the framework to inject transactional logic before and after the method being invoked – mainly for starting and committing the transaction.

What is important to keep in mind is that, if the transactional bean is implementing an interface, by default the proxy will be a Java Dynamic Proxy. This means that only external method calls that come in through the proxy will be intercepted – any self-invocation calls will not start any transaction – even if the method is annotated with @Transactional.

Another caveat of using proxies is that only public methods should be annotated with @Transactional – methods of any other visibilities will simply ignore the annotation silently as these are not proxied.

This article discusses further proxying pitfals in great detail here.

5.2. Changing the Isolation level

One of the major pitfalls when configuring Spring to work with JPA is that changing the isolation of the transaction semantics will not work – JPA does not support custom isolation levels. This is a limitation of JPA, not Spring; nevertheless changing the @Transactional isolation property will result in:

org.springframework.transaction.InvalidIsolationLevelException: Standard JPA does not support custom isolation levels – use a special JpaDialect for your JPA implementation

5.3. Read Only Transactions

The readOnly flag usually generates confusion, especially when working with JPA; from the javadoc:

This just serves as a hint for the actual transaction subsystem; it will not necessarily cause failure of write access attempts. A transaction manager which cannot interpret the read-only hint will not throw an exception when asked for a read-only transaction.

The fact is that it cannot be guaranteed that an insert or update will not occur when the readOnly flag is set – its behavior is vendor dependent whereas JPA is vendor agnostic.

It is also important to understand that the readOnly flag is only relevant inside a transaction; if an operation occurs outside of a transactional context, the flag is simply ignored. A simple example of that would calling a method annotated with:

@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )

from a non-transactional context – a transaction will not be created and the readOnly flag will be ignored.

5.4. Transaction Logging

Transactional related issues can also be better understood by fine-tuning logging in the transactional packages; the relevant package in Spring is “org.springframework.transaction”, which should be configured with a logging level of TRACE.

6. Conclusion

We covered the basic configuration of transactional semantics using both java and XML, how to use @Transactional and best practices of a Transactional Strategy. The Spring support for transactional testing as well as some common JPA pitfalls were also discussed.

The implementation of this simple project can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

Reference: Transactions with Spring 3 and JPA from our JCG partner Eugen Paraschiv at the baeldung blog.
Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

One Response to "Transaction configuration with JPA and Spring 3.1"

  1. MK says:

    So what do I do if I do need to change transaction isolation level on a transaction which includes JPA?

Leave a Reply

− 7 = one

Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books