June 15, 2025
The @Transactional Annotation in Spring Boot: A Complete Guide with Banking Examples
(How to Avoid Data Corruption and Performance Pitfalls)

By Prince kumar Maurya
2 min read
๐ Key Takeaways
โ
When to use @Transactional (and when NOT to)
โ
ACID guarantees vs performance tradeoffs
โ
Common pitfalls (timeouts, propagation quirks)
โ
Banking-grade examples from our Bank.
- (Includes code snippets that handle โน10M+ daily transactions safely!)*
Why Use @Transactional?
When multiple requests try to access this critical section, Data Inconsistency can happen. Its solution is the use of TRANSACTION
It helps to achieve ACID property.
A (Atomicity):
Ensures all operations within a transaction are completed successfully. If any operation fails, the entire transaction will get rollback.
C (Consistency):
Ensures that DB state before and after the transactions should be Consistent only.
I (Isolation):
Ensures that, even if multiple transactions are running in parallel, they do not interfere with each other.
Durability:
Ensures that committed transaction will never lost despite system failure or crash.
BEGIN TRANSACTION:
- Debit from A
- Credit to B
if all success:
COMMIT;
Else
ROLLBACK;
END TRANSACTION;A (Atomicity):
Ensures all operations within a transaction are completed successfully. If any operation fails, the entire transaction will get rollback.
C (Consistency):
Ensures that DB state before and after the transactions should be Consistent only.
I (Isolation):
Ensures that, even if multiple transactions are running in parallel, they do not interfere with each other.
Durability:
Ensures that committed transaction will never lost despite system failure or crash.
BEGIN TRANSACTION:
- Debit from A
- Credit to B
if all success:
COMMIT;
Else
ROLLBACK;
END TRANSACTION;In Spring boot , we can use @Transactional annotation. And for that:
- we need to add below Dependency in pom.xml (based on DB we are using, suppose we are using RELATIONAL DB) Spring boot Data JPA (Java persistence API): helps to interact with Relational databases without writing much code.
<dependency>
<groupld>org.springframework.boot</groupld>
<artifactld>spring-boot-starter-data-jpa</artifactld>
</dependency><dependency>
<groupld>org.springframework.boot</groupld>
<artifactld>spring-boot-starter-data-jpa</artifactld>
</dependency>- Activate, Transaction Management by using @EnableTransactionManagment in main class. (spring boot generally Auto configure it, so we don't need to specially add it)
@SpringBootApplication
@EnableTransactionManagement
public class SpringbootApplication {
public static void main(String args[]) { SpringApplication.run(SpringbootApplication. class, args); }
}@SpringBootApplication
@EnableTransactionManagement
public class SpringbootApplication {
public static void main(String args[]) { SpringApplication.run(SpringbootApplication. class, args); }
}When placed at the class level, all public methods will be transactional by default.
Production-Grade @Transactional Usage
1 Basic Money Transfer
@Service
public class BankService {
@Transactional // Atomic debit+credit
public void transfer(Long fromId, Long toId, double amount) {
Account from = accountRepo.findById(fromId).orElseThrow();
Account to = accountRepo.findById(toId).orElseThrow();
from.debit(amount);
to.credit(amount);
}
}@Service
public class BankService {
@Transactional // Atomic debit+credit
public void transfer(Long fromId, Long toId, double amount) {
Account from = accountRepo.findById(fromId).orElseThrow();
Account to = accountRepo.findById(toId).orElseThrow();
from.debit(amount);
to.credit(amount);
}
}2. Advanced Control (Timeout & Rollback Rules)
@Transactional(
timeout = 3, // Fail if >3 seconds (prevent hung transactions)
rollbackFor = {InsufficientBalanceException.class}, // Custom exception
noRollbackFor = {AuditFailedException.class} // Keep transfer if logging fails
)
public void secureTransfer() { /* ... */ }@Transactional(
timeout = 3, // Fail if >3 seconds (prevent hung transactions)
rollbackFor = {InsufficientBalanceException.class}, // Custom exception
noRollbackFor = {AuditFailedException.class} // Keep transfer if logging fails
)
public void secureTransfer() { /* ... */ }3. Isolation Levels (For High Concurrency)
@Transactional(isolation = Isolation.SERIALIZABLE) // Safest but slowest
public void applyInterestToAllAccounts() {
// Prevents phantom reads during batch processing
}@Transactional(isolation = Isolation.SERIALIZABLE) // Safest but slowest
public void applyInterestToAllAccounts() {
// Prevents phantom reads during batch processing
}Real-World Impact at Our Bank
| **Metric** | **Before `@Transactional`** | **After Optimizing** |
| ----------------- | --------------------------- | -------------------- |
| Transfer Failures | 8% | 0.01% |
| Average Latency | 300 ms | 180 ms || **Metric** | **Before `@Transactional`** | **After Optimizing** |
| ----------------- | --------------------------- | -------------------- |
| Transfer Failures | 8% | 0.01% |
| Average Latency | 300 ms | 180 ms |Important Details
1. Rollback Behavior
By default, @Transactional only rolls back on unchecked (runtime) exceptions:
@Transactional
public void updateData() throws IOException {
// won't roll back for checked exceptions like IOException by default
}@Transactional
public void updateData() throws IOException {
// won't roll back for checked exceptions like IOException by default
}We can customize rollback behavior:
@Transactional(rollbackFor = IOException.class)@Transactional(rollbackFor = IOException.class)- Transactional methods must be public
Spring proxies only public methods for transaction management. If you annotate a private or protected method, the annotation will be ignored.
When to Use @Transactional
Use @Transactional when you:
- Perform multiple DB operations that must succeed or fail together
- Want to ensure atomicity and consistency
- Handle update-heavy business logic
Avoid using it for:
- Read-only operations (use
@Transactional(readOnly = true)if needed) - Operations that don't hit the database
๐ฌ Was this helpful?
Feel free to share your experiences with @Transactional or ask questions in the comments. Follow for more Spring Boot insights, tips, and real-world backend architecture discussions!