Why Spring @Transactional May Not Roll Back on Checked Exceptions—and How to Fix It

This article explains the AOP mechanism behind Spring's @Transactional, why only unchecked exceptions trigger automatic rollbacks, illustrates common pitfalls with code examples, and provides practical fixes such as using rollbackFor or manually marking the transaction for rollback.

JavaEdge
JavaEdge
JavaEdge
Why Spring @Transactional May Not Roll Back on Checked Exceptions—and How to Fix It

1. How AOP Implements Transaction Management

Spring wraps a method annotated with @Transactional in a try/catch block. When the method throws an exception that satisfies the rollback condition, the catch block triggers a transaction rollback; otherwise the transaction is committed.

If the method throws an exception that meets the configured conditions, the transaction is rolled back.

If no exception is thrown, the transaction is committed.

The conditions are that the exception must be a RuntimeException or Error by default. Checked (or "受检") exceptions do not cause a rollback unless explicitly configured.

Spring’s core logic resides in TransactionAspectSupport#invokeWithinTransaction, which only proceeds with rollback when an exception is captured.

2. Counter‑Examples (Common Bugs)

2.1 Registration User Cases

createUserError1 throws a RuntimeException, but the method catches all exceptions, preventing the exception from propagating out of the @Transactional method, so the transaction is not rolled back.

createUserError2 calls readFile. When readFile throws a checked exception, the exception propagates as a checked exception, and Spring’s default policy does not roll back the transaction.

Both methods demonstrate that improper exception handling can prevent the expected rollback.

2.2 How to Fix the Bugs

Use logs to verify whether the rollback was successful. The following fixes are recommended:

Do not catch exceptions inside a @Transactional method, or re‑throw them as unchecked exceptions.

Manually mark the transaction for rollback when you catch an exception:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

Configure @Transactional(rollbackFor = Exception.class) (or specific checked exceptions) to override the default behavior.

After applying the fix, logs show the message "Transactional code has requested rollback", confirming the transaction was rolled back.

Transactional code has requested rollback : manual rollback request.

3. Summary

Incorrect exception handling often leads to transactions that commit even when errors occur. Spring rolls back only for RuntimeException and Error by default; checked exceptions require explicit configuration via rollbackFor or manual rollback calls. Adjusting the exception handling or transaction attributes ensures consistent rollback behavior across database and I/O operations.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavatransactionaopspring
JavaEdge
Written by

JavaEdge

First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.