Spring Boot Transaction Management

1. Introduction

Transaction Management in Spring Boot ensures that multiple database operations behave as a single logical unit of work.

If all operations succeed → COMMIT
If any operation fails → ROLLBACK

This guarantees data consistency and integrity.

Bank Transfer Example

Step 1: Debit amount from Account A
Step 2: Credit amount to Account B
Either BOTH succeed
OR
BOTH fail

2. ACID Properties of Transactions

Property Meaning
Atomicity All operations succeed or all fail
Consistency Database remains in valid state
Isolation Transactions do not interfere
Durability Committed data is permanent
Transaction Start
   ↓
Update Account A
   ↓
Update Account B
   ↓
Commit
Transaction Start
   ↓
Update Account A
   ↓
Error occurs
   ↓
Rollback

3. Spring Boot Transaction Architecture

Client
  ↓
Service Layer
  ↓
@Transactional Proxy
  ↓
Transaction Manager
  ↓
Repository / DAO
  ↓
Database
Layer Responsibility
Client Calls service method
Service Contains business logic
Transaction Proxy Handles transaction boundaries
Transaction Manager Begins / commits / rollbacks
Repository Executes SQL

4. Transaction Manager in Spring Boot

Transaction Manager Used With
DataSourceTransactionManager JDBC
JpaTransactionManager JPA / Hibernate
HibernateTransactionManager Hibernate
JtaTransactionManager Distributed transactions

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {

    return new DataSourceTransactionManager(dataSource);

}

5. @Transactional Annotation

The @Transactional annotation enables transaction management.


@Service
public class PaymentService {

    @Transactional
    public void transferMoney(Long fromId, Long toId, double amount) {

        accountRepository.debit(fromId, amount);
        accountRepository.credit(toId, amount);

    }

}
Start Transaction
    ↓
Debit Account
    ↓
Credit Account
    ↓
Success → COMMIT
Failure → ROLLBACK

6. Real World Example (Spring Boot + JPA)

Entity


@Entity
public class Account {

    @Id
    @GeneratedValue
    private Long id;

    private String name;
    private double balance;

}

Repository


@Repository
public interface AccountRepository extends JpaRepository {

}

Service Layer


@Service
public class AccountService {

    @Autowired
    private AccountRepository accountRepository;

    @Transactional
    public void transfer(Long fromId, Long toId, double amount) {

        Account fromAccount = accountRepository.findById(fromId).orElseThrow();
        Account toAccount = accountRepository.findById(toId).orElseThrow();

        fromAccount.setBalance(fromAccount.getBalance() - amount);
        toAccount.setBalance(toAccount.getBalance() + amount);

        accountRepository.save(fromAccount);
        accountRepository.save(toAccount);
    }

}

7. Transaction Propagation

Propagation Type Description
REQUIRED Join existing transaction or create new
REQUIRES_NEW Always create new transaction
SUPPORTS Use existing transaction if available
NOT_SUPPORTED Run without transaction
MANDATORY Must run inside transaction
NEVER Must run without transaction
NESTED Nested transaction

@Transactional(propagation = Propagation.REQUIRED)
public void processOrder(){

}

8. Transaction Isolation Levels

Isolation Level Description
READ_UNCOMMITTED Dirty reads allowed
READ_COMMITTED Only committed data
REPEATABLE_READ Same row returns same result
SERIALIZABLE Highest isolation

@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateInventory(){

}

9. Rollback Rules

Rollback occurs for:

RuntimeException
Error

@Transactional(rollbackFor = Exception.class)
public void processPayment() throws Exception{

}

10. Best Practices

✔ Keep transactions in Service Layer
✔ Use @Transactional at method level
✔ Keep transactions short
✔ Use readOnly for queries
✔ Avoid transactions in Controller

11. Interview Questions

What annotation enables transactions?

@Transactional

Default propagation?

REQUIRED

Where should transactions be used?

Service Layer