Spring Data JPA Transaction Management

Blue futuristic stream Data Communication flying into digital technologic animation 3D rendering
Reading Time: 3 minutes

Spring Data JPA Transaction Management :

A Spring Data JPA Transaction Management has a sequence of actions that are bundled as a single piece of work.

It is an important part of RDMBS-oriented applications to ensure data consistency and integrity.

The transaction is a set of SQL statements that is naturally automatic in nature to manage the data.

It has the following four key properties ACID –

• Atomicity— It refers to whether the entire transaction takes place at once or doesn’t happen at all.

• Consistency—The database must be consistent before and after the transactions are done.

• Isolation—Multiple transactions occur independently without any interference.

• Durability—The changes in a successful transaction occur even if the system failure occurs.

Spring Data JPA Transactional annotation :

The Transactional annotation is used when you want a certain method/class(=all methods inside) to be executed in a transaction.

It will do all the magic we need to do in a programmatic way before handling transaction management.

Any bean’s public method you annotate with the @Transactional annotation will be executed within transaction management.

Example of Spring Data JPA with Transaction Management :

Spring Data JPA Transaction Management

If assume the real-time scenario wants to book a flight ticket we required the Passenger Info and Payment Info details.

Store that data into any RDBMS databases as per requirement.

Any Passenger is not booked the ticket and Payment got failure for any reason due to Payment gateway or network error or any other else.

There is no point to store the unwanted data in the database and for such a case we are not able to generate the acknowledgment for it.

To avoid data inconsistency the transaction management comes either to commit or rollback.

Following is pom.xml, with added dependencies for JPA.

<?xml version="1.0" encoding="UTF-8"?>

<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

 https://maven.apache.org/xsd/maven-4.0.0.xsd">

	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>org.springframework.boot</groupId>

		<artifactId>spring-boot-starter-parent</artifactId>

		<version>2.7.3</version>

		<relativePath/> <!-- lookup parent from repository -->

	</parent>

	<groupId>com.knoldus</groupId>

	<artifactId>flight-service-example</artifactId>

	<version>0.0.1-SNAPSHOT</version>

	<name>flight-service-example</name>

	<description>Demo project for Spring Boot with-transaction</description>

	<properties>

		<java.version>1.8</java.version>

	</properties>


	<dependencies>

		<dependency>

			<groupId>org.springframework.boot</groupId>

			<artifactId>spring-boot-starter-data-jpa</artifactId>

		</dependency>

		<dependency>

			<groupId>org.springframework.boot</groupId>

			<artifactId>spring-boot-starter-web</artifactId>

		</dependency>

		<dependency>

			<groupId>mysql</groupId>

			<artifactId>mysql-connector-java</artifactId>

			<scope>runtime</scope>

		</dependency>

		<dependency>

			<groupId>org.projectlombok</groupId>

			<artifactId>lombok</artifactId>

			<optional>true</optional>

		</dependency>

		<dependency>

			<groupId>org.springframework.boot</groupId>

			<artifactId>spring-boot-starter-test</artifactId>

			<scope>test</scope>

		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>

				<artifactId>spring-boot-maven-plugin</artifactId>

			</plugin>
		</plugins>
	</build>

</project>

Create an application.properties as below –

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url = jdbc:mysql://localhost:3306/knoldus_db

spring.datasource.username = root

spring.datasource.password = root

spring.jpa.show-sql = true

spring.jpa.hibernate.ddl-auto = update

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect

server.port=9090

Create the appropriate service class and repository classes for Passenger and Payment –

package com.knoldus.transaction.service;

import com.knoldus.transaction.dto.FlightBookingAcknowledgement;

import com.knoldus.transaction.dto.FlightBookingRequest;

import com.knoldus.transaction.entity.PassengerInfo;

import com.knoldus.transaction.entity.PaymentInfo;

import com.knoldus.transaction.repository.PassengerInfoRepository;

import com.knoldus.transaction.repository.PaymentInfoRepository;

import com.knoldus.transaction.utils.PaymentUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@Service

public class FlightBookingService {

    @Autowired

    private PassengerInfoRepository passengerInfoRepository;

    @Autowired

    private PaymentInfoRepository paymentInfoRepository;


    @Transactional //(readOnly = false,isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)

    public FlightBookingAcknowledgement bookFlightTicket(FlightBookingRequest request) {


        PassengerInfo passengerInfo = request.getPassengerInfo();

        passengerInfo = passengerInfoRepository.save(passengerInfo);

        PaymentInfo paymentInfo = request.getPaymentInfo();


        PaymentUtils.validateCreditLimit(paymentInfo.getAccountNo(), passengerInfo.getFare());

        paymentInfo.setPassengerId(passengerInfo.getPId());

        paymentInfo.setAmount(passengerInfo.getFare());

        paymentInfoRepository.save(paymentInfo);

        return new FlightBookingAcknowledgement("SUCCESS", passengerInfo.getFare(), UUID.randomUUID().toString().split("-")[0], passengerInfo);

    }
}

Main Application

FlightServiceExampleApplication is the main class, which contains test data to test transaction management. Used @EnableTransactionManagement annotation.

package com.knoldus.transaction;

import com.knoldus.transaction.dto.FlightBookingAcknowledgement;

import com.knoldus.transaction.dto.FlightBookingRequest;

import com.knoldus.transaction.service.FlightBookingService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

importorg.springframework.transaction.annotation.EnableTransactionManagement;

import org.springframework.web.bind.annotation.PostMapping; 

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication

@RestController

@EnableTransactionManagement

public class FlightServiceExampleApplication {

   @Autowired

   private FlightBookingService service;


   @PostMapping("/bookFlightTicket")

   public FlightBookingAcknowledgement bookFlightTicket(@RequestBody FlightBookingRequest request){

      return service.bookFlightTicket(request);

   }

   public static void main(String[] args) {

      SpringApplication.run(FlightServiceExampleApplication.class, args);
   }

}

Run the application by using the IDE Run option or by using the below command

mvn spring-boot:run

Results :

Passenger Table
Payment Table

References :

https://github.com/knoldus/Spring-Transaction-Demo-with-Spring-data-JPA

Written by 

Strong in design and integration problem-solving skills. Experience in Java/J2EE with database analysis and design. Skilled in developing business plans, requirements specifications, user documentation, and architectural systems research. Having Good Work Experience with Core Java, Advanced Java, Typescript, and Related Technologies, AWS like S3, Lambda, EC2, Elemental Live, Media Live, Tesseracts, and Textract.