Understanding the Spring Transaction Rollback Bug and Its Resolution

This article analyzes a Spring transaction rollback issue caused by the use of pattern‑based exception matching, explains why certain custom exceptions trigger unexpected rollbacks, traces the problem through source code and GitHub issues, and describes how the Spring team fixed it with type‑safe rollback rules and documentation updates.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding the Spring Transaction Rollback Bug and Its Resolution

Background

The author received a question about a Spring transaction that behaved unexpectedly: an exception annotated with @Transactional(rollbackFor = AgeException.class) caused a rollback even when the thrown exception was AgeExceptionOver18, which should not be rolled back.

Demo Setup

A simple demo project is built to reproduce the issue, inserting users of different ages and configuring rollback rules to illustrate when the transaction is committed or rolled back.

Investigation

By stepping through TransactionAspectSupport#invokeWithinTransaction and RollbackRuleAttribute#rollbackOn, the author discovers that Spring uses String.contains() to match exception names, causing AgeExceptionOver18 to match the configured AgeException rule.

The matching logic checks the depth of the rule with int depth = rule.getDepth(ex), and a non‑null depth leads to a rollback.

Root Cause

The use of contains() was originally intended to support simple class names in XML configuration, but it also unintentionally matches subclasses, nested classes, and similarly named exceptions.

Community Discussion

The issue was reported on GitHub (issues #28098, #24682) and went through several title changes and triage stages. Contributors argued for a more precise matching strategy, and the Spring team acknowledged the problem.

Resolution

Spring introduced type‑safe rollback rules: when a concrete exception class is provided, the matching uses equals() on the fully‑qualified class name; pattern‑based matching with contains() remains for string‑based configurations.

The fix adds an exceptionType field to RollbackRuleAttribute and updates the matching logic accordingly, preventing accidental rollbacks for nested or similarly named exceptions.

Conclusion

The article demonstrates how a seemingly minor design choice in exception matching can lead to bugs, how community feedback drives framework improvements, and why understanding the underlying transaction mechanics is essential for robust backend development.

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.

BackendJavatransactionspringDocumentationbugrollback
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

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.