0% found this document useful (0 votes)
7 views23 pages

Spring Boot_Transaction Management

The document explains transaction management in Spring Boot using the @Transactional annotation, which helps ensure data consistency by managing operations as a single transaction. It outlines the importance of transaction management through examples, such as booking a flight ticket, and provides a step-by-step guide for implementing transaction management in a Spring Boot application. Additionally, it categorizes different types of transactions, including flat, nested, distributed, and compensating transactions.

Uploaded by

ankitagorde4386
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
7 views23 pages

Spring Boot_Transaction Management

The document explains transaction management in Spring Boot using the @Transactional annotation, which helps ensure data consistency by managing operations as a single transaction. It outlines the importance of transaction management through examples, such as booking a flight ticket, and provides a step-by-step guide for implementing transaction management in a Spring Boot application. Additionally, it categorizes different types of transactions, including flat, nested, distributed, and compensating transactions.

Uploaded by

ankitagorde4386
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 23

Spring Boot – Transaction Management Using @Transactional

Annotation

Last Updated : 04 Jan, 2025

@Transactional annotation is the metadata used for managing


transactions in the Spring Boot application. To configure Spring
Transaction, this annotation can be applied at the class level or method
level. In an enterprise application, a transaction is a sequence of actions
performed by the application that together pipelined to perform a single
operation. For example, booking a flight ticket is also a transaction where
the end user has to enter his information and then make a payment to
book the ticket.

Why Do We Need Transaction Management?

Let’s understand transactions with the above example, if a user has


entered his information the user’s information gets stored in the user_info
table. Now, to book a ticket he makes an online payment and due to some
reason(system failure) the payment has been canceled so, the ticket is not
booked for him. But, the problem is that his information gets stored on the
user_info table. On a large scale, more than thousands of these things
happen within a single day. So, it is not good practice to store a single
action of the transaction(Here, only user info is stored not the payment
info).

To overcome these problems, spring provides transaction management,


which uses annotation to handle these issues. In such a scenario, spring
stores the user information in temporary memory and then checks for
payment information if the payment is successful then it will complete the
transaction otherwise it will roll back the transaction and the user
information will not get stored in the database.

@Transactional Annotation

In Spring Boot, @Transactional annotation is used to manage transactions


in a Spring boot application and used to define a scope of transaction. This
annotation can be applied to the class level or method level. It provides
data reliability and consistency. When a method is indicated with
@Transactional annotation, it indicates that the particular method should
be executed within the context of that transaction. If the transaction
becomes successful then the changes made to the database are
committed, if any transaction fails, all the changes made to that particular
transaction can be rollback and it will ensure that the database remains in
a consistent state.

Note: To use @Transactional annotation, you need to configure


transaction management by using @EnableTransactionManagement
to your main class of Spring Boot application.

Configure Transaction in Spring Boot

In this example, we will create an application to store user information


along with his address information and will use spring transaction
management to resolve the transaction break problem.

Step By Step Implementation of Transaction Management

Step 1: Create A Spring Boot Project

In this step, we will create a spring boot project. For this, we will be
using Spring Initializr. To create a spring boot project please refer to How
to Create a Spring Boot Project?

Step 2: Add Dependencies

We will add the required dependencies for our spring boot application.

Step 3: Configure Database

Now, we will configure the database in our application. We will be using


the following configurations and add them to
our application.properties file.

server.port = 9090
#database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/employee_db
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dial
ect
#the ddl-auto=update : It will create the entity schema and map it to db
automatically
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Note: Please add your database username & password along with the
database path.

Step 4: Create Model Class

In this step, we will create our model class. Here, we will be creating two
model classes, Employee and Address. While creating the model class
we will be using Lombok Library.

Employee.java

import jakarta.persistence.Entity;

import jakarta.persistence.GeneratedValue;

import jakarta.persistence.GenerationType;

import jakarta.persistence.Id;

import jakarta.persistence.Table;

import lombok.AllArgsConstructor;

import lombok.Getter;

import lombok.NoArgsConstructor;

import lombok.Setter;

import lombok.ToString;

@Getter

@Setter

@NoArgsConstructor

@AllArgsConstructor

@ToString

@Entity
@Table(name="EMP_INFO")

public class Employee {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int id;

private String name;

Address.java

import jakarta.persistence.Entity;

import jakarta.persistence.GeneratedValue;

import jakarta.persistence.GenerationType;

import jakarta.persistence.Id;

import jakarta.persistence.OneToOne;

import jakarta.persistence.Table;

import lombok.AllArgsConstructor;

import lombok.Getter;

import lombok.NoArgsConstructor;

import lombok.Setter;

import lombok.ToString;

@Getter

@Setter

@NoArgsConstructor

@AllArgsConstructor

@ToString

@Entity

@Table(name="ADD_INFO")
public class Address {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private Long id;

private String address;

// one to one mapping means,

// one employee stays at one address only

@OneToOne

private Employee employee;

Step 5: Create a Database Layer

In this step, we will create a database layer. For this, we will be


creating EmployeeRepository and AddressRepository and will be
extending JpaRepository<T, ID> for performing database-related
queries.

EmployeeRepository.java

import org.springframework.data.jpa.repository.JpaRepository;

import
com.geeksforgeeks.transactionmanagement.model.Employee;

public interface EmployeeRepository extends


JpaRepository<Employee, Integer> {

AddressRepository.java

import org.springframework.data.jpa.repository.JpaRepository;

import
com.geeksforgeeks.transactionmanagement.model.Address;
public interface AddressRepository extends JpaRepository<Address,
Integer> {

Step 6: Create a Service Layer

You can use @Transactional annotation in service layer which will result
interacting with the database. In this step, we will create a service layer
for our application and add business logic to it. For this, we will be
creating two classes EmployeeService and AddressService. In
EmployeeService class we are throwing an exception.

EmployeeService.java

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

import org.springframework.stereotype.Service;

import
org.springframework.transaction.annotation.Transactional;

import
com.geeksforgeeks.transactionmanagement.model.Address;

import
com.geeksforgeeks.transactionmanagement.model.Employee;

import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;

@Service

public class EmployeeService {

@Autowired

private EmployeeRepository employeeRepository;

@Autowired
private AddressService addressService;

@Transactional

public Employee addEmployee(Employee employee) throws Exception


{

Employee employeeSavedToDB =
this.employeeRepository.save(employee);

Address address = new Address();

address.setId(123L);

address.setAddress("Varanasi");

address.setEmployee(employee);

// calling addAddress() method

// of AddressService class

this.addressService.addAddress(address);

return employeeSavedToDB;

AddressService.java

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

import org.springframework.stereotype.Service;

import
com.geeksforgeeks.transactionmanagement.model.Address;

import
com.geeksforgeeks.transactionmanagement.repository.AddressR
epository;

@Service

public class AddressService {


@Autowired

private AddressRepository addressRepository;

public Address addAddress(Address address) {

Address addressSavedToDB = this.addressRepository.save(address);

return addressSavedToDB;

Step 7: Create Controller

In this step, we will create a controller for our application. For this, we will
create a Controller class and add all the mappings to it.

Controller.java

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

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

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

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

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

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

import
com.geeksforgeeks.transactionmanagement.model.Employee;

import
com.geeksforgeeks.transactionmanagement.service.EmployeeSer
vice;

@RestController

@RequestMapping("/api/employee")
public class Controller {

@Autowired

private EmployeeService employeeService;

@PostMapping("/add")

public ResponseEntity<Employee> saveEmployee(@RequestBody


Employee employee) throws Exception{

Employee employeeSavedToDB =
this.employeeService.addEmployee(employee);

return new ResponseEntity<Employee>(employeeSavedToDB,


HttpStatus.CREATED);

Step 8: Running Our Application

In this step, we will run our application. Once, we run our application using
hibernate mapping in our database required tables will be created.

As we can see in logs, our table has been created. We can also confirm it
by looking at our database.
Now, we will request our application for adding an employee to it, using
postman. To learn more about postman please refer to Postman – Working,
HTTP Request & Responses. Once, we hit the request, the request
moves from the controller to the service layer where our business
logic is present.
As we can see in the above response we have added an employee. We
can also check our database for employee data and address data.

Similarly, we can also check for address data.


Step 9: Problem Without Transaction Management

In the EmployeeService class, we initialize the address object to NULL.


Consequently, the employee’s details cannot be stored in the database
due to the null address object. However, as we are not employing
transaction management, the employee basic information will persisted in
the database. The address details are omitted because of the null value.

Note: Applying the @Transactional annotation to a method will not


trigger a rollback of any operation if @EnableTransactionManagement
is not used.

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

import org.springframework.stereotype.Service;

import
org.springframework.transaction.annotation.Transactional;

import
com.geeksforgeeks.transactionmanagement.model.Address;

import
com.geeksforgeeks.transactionmanagement.model.Employee;
import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;

@Service

public class EmployeeService {

@Autowired

private EmployeeRepository employeeRepository;

@Autowired

private AddressService addressService;

public Employee addEmployee(Employee employee) throws Exception


{

Employee employeeSavedToDB =
this.employeeRepository.save(employee);

// we will initialize the

// address object as null

Address address = null;

address.setId(123L);

address.setAddress("Varanasi");

address.setEmployee(employee);

// calling addAddress() method

// of AddressService class

this.addressService.addAddress(address);

return employeeSavedToDB;

}
}

Now, we will delete our table from the database and again run our
application and will request the application to create an employee.

As we can see in the above media file, we have initialized the address
object as null and requested the application, we have an employee
created in the database but the address information is not, as we have
received a null pointer exception. But, this is not good practice in
transaction management, as employees should be saved only when the
address is saved and vice-versa.

Step 10: Transaction Management

To overcome this problem, we will use @Transactional annotation. This


will ensure that the transaction should be complete. That is, either both
employee and address data should be stored or nothing will get
stored. For using transaction management, we need to
use @EnableTransactionManagement in the main class of our
spring boot application and also, and we need to annotate
our addEmployee() method in EmployeeService class
with @Transactional annotation.

TransactionManagementApplication.java

import org.springframework.boot.SpringApplication;

import
org.springframework.boot.autoconfigure.SpringBootApplication;

import
org.springframework.transaction.annotation.EnableTransactionM
anagement;

@SpringBootApplication

@EnableTransactionManagement

public class TransactionManagementApplication {

public static void main(String[] args) {

SpringApplication.run(TransactionManagementApplication.class,
args);

}
}

EmployeeService.java

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

import org.springframework.stereotype.Service;

import
org.springframework.transaction.annotation.Transactional;

import
com.geeksforgeeks.transactionmanagement.model.Address;

import
com.geeksforgeeks.transactionmanagement.model.Employee;

import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;

@Service

public class EmployeeService {

@Autowired

private EmployeeRepository employeeRepository;

@Autowired

private AddressService addressService;

@Transactional

public Employee addEmployee(Employee employee) throws Exception


{

Employee employeeSavedToDB =
this.employeeRepository.save(employee);

// we will initialize the


// address object as null

Address address = null;

address.setId(123L);

address.setAddress("Varanasi");

address.setEmployee(employee);

// calling addAddress() method

// of AddressService class

this.addressService.addAddress(address);

return employeeSavedToDB;

Step 11: Running Application

Now, we have enabled transaction management for our application. We


will again delete the tables from our database and request our application
to add an employee.

As we can see in the above media file, this time the employee data do not
get stored in the database, nor did the address data. This way the spring
has handled the transaction that both employees and address data gets
stored or no data gets stored.

Conclusion

In this article, we have learned basic configuration of transaction


management using in a Spring Boot application. Also we have covered
@Transactional and @EnableTransactionManagement annotation and it’s
uses with a step by step implementation in a spring boot application.

Types of Transactions in Database and Software Systems

Transactions are classified based on their scope, complexity, and the


systems they interact with. Below are the primary types:

1. Flat Transactions

 Definition: A simple transaction with a single start and end point.


 Characteristics:

o Consists of one operation or multiple tightly coupled


operations.

o Either fully completes (commit) or reverts (rollback).

 Example:

o Updating a user's email address in a database.

 BEGIN;

 UPDATE users SET email = 'newemail@example.com' WHERE id = 1;

 COMMIT;

2. Nested Transactions

 Definition: A transaction containing one or more sub-transactions.

 Characteristics:

o Parent transaction can commit only if all child transactions


commit.

o If a child transaction fails, its effects are rolled back without


affecting other children.

 Example:

o A banking system where:

 A parent transaction debits an account.

 Child transactions handle inter-account transfers.

 Parent Transaction:

 - Start

 - Debit account

 - Commit if all child transactions succeed

 Child Transactions:

 - Transfer 1

 - Transfer 2

3. Distributed Transactions
 Definition: A transaction spanning multiple databases, systems, or
services.

 Characteristics:

o Requires a transaction coordinator for two-phase commit


(2PC) or similar protocols.

o Used in microservices or systems with multiple databases.

 Example:

o Booking a vacation:

 Flight reservation in one system.

 Hotel booking in another system.

 Payment processing in a third system.

4. Chained Transactions

 Definition: A sequence of transactions where each depends on the


previous one’s success.

 Characteristics:

o Useful for workflows where operations are interdependent.

 Example:

o A shipment system:

 Order processing → Payment confirmation → Shipping


initiation.

5. Compensating Transactions

 Definition: A rollback mechanism for long-running or complex


transactions where a direct rollback is not feasible.

 Characteristics:

o Used in systems that cannot lock resources for long durations.

o Instead of undoing actions, compensatory actions are


executed.

 Example:
o If an order cancellation occurs after the payment is processed,
a refund is initiated as compensation.

6. Long-Running Transactions

 Definition: Transactions that require extended durations to


complete.

 Characteristics:

o Involve breaking down into smaller units with periodic saving


points.

o Often used in workflows like batch processing.

 Example:

o ETL (Extract, Transform, Load) operations in data warehouses.

7. Savepoint Transactions

 Definition: Transactions that allow partial rollback to specific points


within the transaction.

 Characteristics:

o Savepoints act as markers for partial undo operations.

 Example:

 BEGIN;

 INSERT INTO orders VALUES (1, 'Order1');

 SAVEPOINT sp1;

 INSERT INTO orders VALUES (2, 'Order2');

 ROLLBACK TO sp1; -- Rolls back to sp1 but keeps 'Order1'

 COMMIT;

8. Multi-Level Transactions

 Definition: A generalization of nested transactions where sub-


transactions are hierarchically dependent.

 Characteristics:
o Provides flexibility in managing the relationships between sub-
transactions.

 Example:

o Hierarchical business workflows, such as multi-department


approval processes.

9. Read-Only Transactions

 Definition: Transactions that only read data and do not modify it.

 Characteristics:

o Ensures high performance by not locking resources for


updates.

 Example:

o Generating a report using a SELECT query:

o BEGIN;

o SELECT * FROM sales WHERE month = 'January';

o COMMIT;

10. Explicit and Implicit Transactions

 Explicit Transactions:

o Started and committed/rolled back explicitly by the developer.

o Example:

o BEGIN TRANSACTION;

o UPDATE accounts SET balance = balance - 100 WHERE id = 1;

o COMMIT;

 Implicit Transactions:

o Automatically managed by the database system without


explicit commands.

o Example:

 MySQL auto-commits each SQL statement unless


explicitly wrapped in a transaction.
11. ACID Transactions

 Definition: Transactions adhering strictly to Atomicity, Consistency,


Isolation, and Durability principles.

 Characteristics:

o Typically found in relational database systems.

 Example:

o Bank fund transfer ensuring no partial updates.

12. BASE Transactions

 Definition: Transactions in distributed systems focusing on


Basically Available, Soft state, Eventually consistent
principles.

 Characteristics:

o Sacrifices strict consistency for high availability.

o Used in NoSQL systems like DynamoDB or Cassandra.

Real-World Examples

Type Use Case

Flat Transactions Updating user profile details.

Nested Transactions Bank transfers involving multiple accounts.

Distributed E-commerce systems spanning inventory,


Transactions payment, and delivery.

Savepoint Transactions Handling partial updates in batch processing.

Compensating
Refunding a customer after order cancellation.
Transactions

Let me know if you'd like a deeper dive into any specific type!

Transaction Management in Detail


Transaction Management is a critical concept in software development,
particularly in systems dealing with databases. It ensures the ACID
(Atomicity, Consistency, Isolation, Durability) properties of a
transaction, which are essential for maintaining data integrity and
reliability.

What is a Transaction?

A transaction is a logical unit of work that includes one or more operations


(like reading or writing data). It must either complete entirely or leave the
system in its original state.

Example:

 Booking a flight ticket involves checking availability, reserving a


seat, and deducting payment. This must happen as a single
transaction.

ACID Properties

1. Atomicity:

o Ensures that all operations within a transaction are completed


successfully. If any operation fails, the entire transaction is
rolled back.

o Example: In a bank transfer, both debit from one account and


credit to another must occur together, or not at all.

2. Consistency:

o Ensures that the database moves from one valid state to


another. It maintains data integrity constraints.

o Example: A transaction should not violate constraints like


primary keys or foreign keys.

3. Isolation:

o Ensures that transactions are executed independently of each


other.

o Example: Two users booking the last available train ticket


should not be able to confirm their transactions
simultaneously.

4. Durability:
o Ensures that the changes made by a completed transaction
are permanently saved in the database, even if a system
failure occurs.

Types of Transactions

1. Flat Transactions:

o A simple transaction with a single start and end point.

o Example: Updating user details in a profile table.

2. Nested Transactions:

o A transaction that contains sub-transactions.

o Example: Placing an order might have sub-transactions for


inventory update, payment processing, and order history
update.

3. Distributed Transactions:

o Transactions that span across multiple databases or systems.

o Example: Banking systems handling interbank fund transfers.

Transaction Management in Java (Spring Framework)

The Spring Framework simplifies transaction management using the


@Transactional annotation.

You might also like