Spring transaction management example using spring boot

In this tutorial, we will see Spring transaction management example using spring boot. First, we will see some basics about Spring Transaction Management then we will see a complete example.

We will see how to use @Transactional annotation, what will happen if we don’t use @Transaction annotation. We will also cover what are attributes defined for @Transactional annotation and what it does.

The transaction can be defined with ACID properties.

Atomicity – All success or none.
Consistency – Database constraints should not be violated.
Isolation – One transaction should not affect another one.
Durability – It should in Database after commit.

Different ways of transaction management in Spring.

  1. Programmatic transaction management.
  2. Declarative transaction management.

Programmatic transaction management – Here we need to write some extra code for transaction management. When we say some extra code what does it mean? We need to take care of –

  • Creating Transaction reference
  • Begin transaction
  • Commit or rollback of the transaction

Let’s see sample code –

 

Declarative transaction management – No need to write extra code for getting a transaction, we can use annotations or XML-based approach to manage the transactions and we can avoid unnecessary code. If we use annotation based approach we can use @Transactional and if we use the XML-based approach we need to configure DataSourceTransactionManager or any other transaction manager in XML as a bean. In this article and the next upcoming article, we will see the annotation based approach.

Sample code for annotation based declarative transaction management –

 

Sample code for XML-based declarative transaction management –

We have seen basics about Spring transaction management example using spring boot.

Till now we have seen ACID properties and a different approach to implement transaction management. Now we will see how to implement declarative transaction using annotation.

@Transactional this is the key annotation which is responsible for the declarative transaction management. Apart from this annotation, we use @EnableTransactionManagement.

Let’s see what is the advantage of using @Transactional annotation what happens if we don’t use @Transactional annotation. We will also see how to use @Transactional annotation.

@Transactional annotation used with class or method only.

Let’s see a small code snippet which would explain the effect of @Transactional annotation.

Consider you have class BookServiceImpl.java where you have logic to save Book entity.

Observe the saveBook() method. In the above code snippet line number 9 will throw ArithmeticException but before that bookRepository.save(book) will get exected. Now the question comes would we have records in the database or not? In the above scenario even we have an exception in our code have a record in Database.

Which we might don’t want to happen. If we have something wrong in our code data should not persist in the database. Now just modify the code snippet as below, use @Transactional annotation with saveBook() method.

 

Since we are using @Transactional annotation with saveBook() method and we have ArithmeticException at line number 10, our transaction will get rollbacked and we will not have any record in the database.

This is an example which explains what is the benefit of  @Transactional annotation. Although @Transactional annotation does a lot of other stuff which we will cover later in separate tutorials.

So far we have seen effect of using @Transactional annotation. Let’s see what properties have been defined inside @Transactional annotation. We have different properties/attributes with @Transactional annotation so that we can have more control over our transaction. When we say more control over the transaction, what does it mean?

The @Transactional annotation has a different attribute and corresponding value. We can use those attributes and customized our transaction. For example, we have  @Transactional(propagation=Propagation.REQUIRES_NEW), which will create always a new transaction. Let’s see possible attributes of @Transactional annotation.

@Transactional(isolation = Isolation.DEFAULT,
propagation=Propagation.REQUIRES_NEW,
readOnly=true,
noRollbackFor =ArithmeticException.class,
timeout = 30000,
value=”txManager2″,
rollbackFor = { Exception.class },
rollbackForClassName = {“Exception”},
noRollbackForClassName={“Exception”})

So here we have a sample code which elaborates what are the possible attributes for @Transactional. Another point here isolation and propagation attribute has different values. Now it seems a little bit tricky. Yes until unless we are not sure about attributes names and possible values(and what it does exactly, it is not easy to implement in real time development).

 

We will cover more points about Spring transaction management example using spring boot.

Let’s see all attribute/property one by one.

propagation – propagation can have different possible value as below.

  • Propagation.REQUIRED – Support a current transaction, create a new one if none exists.
  • Propagation.REQUIRES_NEW – Always create a new transaction and suspend the current transaction if already exist.
  • Propagation.MANDATORY – Support a current transaction, throw an exception if none exists.
  • Propagation.NESTED – Execute within a nested transaction if a current transaction exists.
  • Propagation.NEVER – Execute non-transactionally, throw an exception if a transaction exists.
  • Propagation.NOT_SUPPORTED – Execute non-transactionally, suspend the current transaction if one exists.
  • Propagation.SUPPORTS – Support a current transaction, execute non-transactionally if none exists.

Propagation.REQUIRED and Propagation.REQUIRES_NEW is frequently used in real-time development. See an example here.

Default Propagation value is Propagation.REQUIRED

isolation – isolation can have different possible value as below.

  • Isolation.READ_UNCOMMITTED – It allows dirty reads, non-repeatable reads, and phantom reads.
  • Isolation.READ_COMMITTED – Dirty reads are prevented, allows non-repeatable and phantom reads.
  • Isolation.REPEATABLE_READ – Dirty reads and non-repeatable prevented, phantom reads allowed.
  • Isolation.SERIALIZABLE – Dirty reads, non-repeatable reads, and phantom reads are prevented.

Default isolation value is Isolation.DEFAULT.

rollbackFor – We can define zero, one or multiple exceptions for which we want our transaction to be rollbacked. We have a separate post where we can find more details.

@Transactional(rollbackFor = {RuntimeException.class})

noRollbackFor – We can define zero, one or multiple exceptions for which we don’t want our transaction to be rollbacked. We have a separate post where we can find more details.

@Transactional(noRollbackFor = {RuntimeException.class})

rollbackForClassName – We can define zero, one or multiple exceptions as String for which we want our transaction to be rollbacked. We have a separate post where we can find more details.

@Transactional(rollbackForClassName = {“NullPointerException”})

noRollbackForClassName – We can define zero, one or multiple exceptions as String for which we don’t want our transaction to be rollbacked. We have a separate post where we can find more details.

@Transactional(noRollbackForClassName = {“NullPointerException”})

readOnly – Its value can be true or false. Go through this post for more details.

@Transactional(readOnly = false)

 

 

Let’s see an example of Spring transaction management example using spring boot.

Prerequisites –

  • JDK 1.8
  • Oracle 10g
  • Eclipse
  • maven
  • postman

We will use the spring boot library (will provide dependency in pom.xml) to make sure all necessary jar/library is easily available for our application. Spring boot will take care of all jar. Let’ s start.

 

Create maven project, Don’t forget to check ‘Create a simple project (skip)’click on next. Fill all details(GroupId – restcontrollerexample, ArtifactId – restcontrollerexample and name – restcontrollerexample) and click on finish. Keep packaging as the jar.

Modify the pom.xml with below code.

Note – In pom.xml we have defined javac.exe path in configuration tag. You need to change accordingly i.e where you have installed JDK.

Let maven download all necessary jar. Once it is done we will able to see maven dependency folder which contains different jar files.

We can start writing our controller classes, ServiceImpl and Repository. The directory structure of the application.

 

Spring transaction management example using spring boot

Define main class SpringMainExample.java

SpringMainExample.java

 

Define entity class i.e Book.java

Book.java

 

Define repository interface extending CrudRepository.

BookRepository.java

 

Define service interface i.e BookService.java

BookService.java

 

Define service implementation class.

BookServiceImpl.java

 

Define the controller class or endpoint.

BookController.java

 

Define JpaConfig class.

 

Step 13 – Define application.properties file

application.properties

 

 

First, we will save one book record using postman.

 

Spring transaction management example using spring boot

 

Now we have one record in DB. Let’s perform get operation

Although we have already discussed, just for reminding In the above example in BookServiceImpl.java, we are using @Transactional annotation with saveBook() method. If we don’t use @Transactional annotation it will work fine we will have a record in DB. But if we modify the BookServiceImpl.java something like below, then we would not have any record in the database. Our transaction will get rollbacked because of ArithmeticException

 

 

Note – It can be ArithmeticException, NullPointerException or any RuntimeException.

Tha’s all about Spring transaction management example using spring boot.

You may like.

Spring Data JPA tutorials.

See Docs here.

 

We have all points about Spring transaction management example using spring boot.

Top