Transaction Management in Spring Boot: Complete Deep Dive
Transaction Management is an essential Spring Boot interview topic because practically every enterprise application performs database operations that must be executed as a complete, atomic unit of work.
Money transfers, order placements, inventory updates, and payroll processing all require strict transactional boundaries. Without transactions, partial updates during a system crash lead directly to fatal data corruption.
1. What is a Transaction?
Standard Definition
A Transaction is a logical unit of work consisting of one or more database operations. It strictly follows an All-or-Nothing rule: Either every operation succeeds completely, or every operation rolls back entirely.
The Bank Transfer Scenario
Suppose you are transferring ₹2000 from Account A to Account B.
- Success Case: Money is deducted from A and added to B. Correct.
- Failure Case: The money is deducted from A, but the server crashes before the second query runs. Account A loses money, Account B gets nothing. The money vanishes.
Transactions solve this. If the second query fails, the database automatically rolls back the first query, restoring Account A's balance to its original state.
2. The ACID Properties (Interview Favorite)
Every transaction guarantees four fundamental properties:
- A - Atomicity: All-or-Nothing. Both the debit and credit succeed, or neither happens.
- C - Consistency: The database state remains valid before and after the transaction. No orphaned records or mathematical impossibilities are allowed.
- I - Isolation: Multiple concurrent transactions do not interfere with each other. If User A and User B modify balances simultaneously, the database isolates their actions to prevent data corruption.
- D - Durability: Once a transaction is successfully committed, the data is permanently written to disk. Even if a sudden power failure occurs a millisecond later, the data survives.
3. Spring's Declarative Solution: @Transactional
Before Spring, managing transactions required massive amounts of manual, repetitive JDBC boilerplate code:
Spring removes this boilerplate via Declarative Transaction Management. You simply annotate your business method with @Transactional.
Internal Flow: Spring automatically begins the transaction, executes your business logic, and commits. If your code throws a RuntimeException, Spring intercepts it and executes a complete rollback.
4. Internal Working of @Transactional (Most Asked Question)
Interview Insight
Most developers know how to use @Transactional. Interviewers ask: How does it work internally?
Answer: @Transactional operates using the Spring AOP Proxy Pattern combined with a TransactionInterceptor.
When Spring detects the @Transactional annotation on a Service bean, it does not give the Controller a direct reference to your Service class. Instead, it generates a Proxy Object wrapper around your class.
PlatformTransactionManager
This is the core engine executing the database commands. Depending on your stack, Spring Boot auto-configures the correct implementation:
DataSourceTransactionManager(For standard JDBC)JpaTransactionManager(For JPA/Hibernate operations)
5. Transaction Attributes
The @Transactional annotation allows deep customization via its attributes:
1. Propagation (How transactions interact)
If Method A (which has a transaction) calls Method B (which also has a transaction), Propagation defines how Method B should behave.
| Propagation Type | Behavior |
|---|---|
| REQUIRED (Default) | If a transaction already exists, join it. If not, create a new one. |
| REQUIRES_NEW | Suspend the current transaction, create a brand new independent transaction, execute, commit, then resume the old transaction. (Often used for Audit Logging). |
| SUPPORTS | If a transaction exists, join it. If not, execute normally without a transaction. |
| MANDATORY | A transaction must exist. If none exists, throw an Exception. |
| NOT_SUPPORTED | Execute non-transactionally. If a transaction exists, suspend it during execution. |
2. Isolation (Handling Concurrency)
Isolation dictates how isolated your transaction is from other concurrent transactions, preventing data corruption anomalies like Dirty Reads, Non-Repeatable Reads, and Phantom Reads.
| Isolation Level | Prevents Dirty Read? | Prevents Non-Repeatable Read? | Prevents Phantom Read? |
|---|---|---|---|
| READ_UNCOMMITTED | No | No | No |
| READ_COMMITTED (Most Common) | Yes | No | No |
| REPEATABLE_READ (MySQL Default) | Yes | Yes | No |
| SERIALIZABLE (Slowest) | Yes | Yes | Yes |
3. Rollback Behavior (rollbackFor)
The Checked Exception Trap
By default, Spring will ONLY rollback a transaction for an Unchecked Exception (RuntimeException or Error).
If your code throws a Checked Exception like IOException, Spring will NOT rollback the transaction!
To force a rollback for checked exceptions, you must explicitly declare it:
4. readOnly & timeout
readOnly = true: Used strictly forSELECTqueries. This is an optimization hint. Hibernate disables its "dirty checking" mechanism, which reduces memory overhead and improves performance.timeout = 10: Specifies that the transaction must complete within 10 seconds. If it exceeds this limit, aTransactionTimedOutExceptionis thrown and a rollback occurs. Ideal for protecting against deadlocks.
6. The Self-Invocation Problem (Crucial Concept)
This is an advanced interview trap. Consider this code:
Question: Will methodB() execute inside a transaction?
Answer: NO.
Because Spring relies on the AOP Proxy wrapper, the proxy is only triggered when an external class calls the method. When methodA() calls methodB() internally (using this.methodB()), the call completely bypasses the proxy object. The @Transactional annotation on methodB() is completely ignored.
7. Best Practices
- Apply at the Service Layer:
@Transactionalbelongs on the Service layer where business logic coordinates multiple repository calls. Do NOT put it on Controllers. - Keep Transactions Small: Never place long-running loops, File Uploads, or slow third-party API HTTP calls inside a transaction. This locks database tables and causes connection pool exhaustion.
- Use Custom RuntimeExceptions: Throw dedicated unchecked exceptions (e.g.,
UserNotFoundException extends RuntimeException) to ensure automatic rollbacks without needingrollbackFor.
8. Interview Checklist Summary
Top Interview Q&A
Q1: What is @Transactional?
A: It is an annotation that allows Spring to manage database transactions declaratively, removing the need for manual connection commit/rollback boilerplate code.
Q2: How does it work internally?
A: Spring uses AOP Proxies. It wraps the target class in a proxy. When a method is called, a TransactionInterceptor catches the call, instructs the PlatformTransactionManager to begin a transaction, executes the method, and triggers a commit or rollback based on success or exception.
Q3: What is the default rollback behavior?
A: It rolls back exclusively for Unchecked Exceptions (RuntimeException and Error). It does not roll back for Checked Exceptions unless configured via rollbackFor.
Q4: What is the default propagation behavior?
A: Propagation.REQUIRED. If a transaction exists, it joins it. If none exists, it creates a new one.
Comments
Post a Comment