Why @Transactional May Not Work: Three Common Failure Scenarios and Their Spring Internals

The article analyzes three typical situations—non‑public methods, internal self‑calls, and caught exceptions—that cause Spring's @Transactional annotation to be ineffective, explains the underlying proxy and AOP mechanisms, and provides Java code samples and test cases to illustrate each case.

Top Architect
Top Architect
Top Architect
Why @Transactional May Not Work: Three Common Failure Scenarios and Their Spring Internals

This article explains why the @Transactional annotation sometimes fails to start a transaction in Spring applications and presents three typical failure scenarios.

Scenario 1 – Non‑public method: When a method annotated with @Transactional is not declared public, Spring’s proxy mechanism ignores it because

AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

returns null for non‑public methods. The article shows a class with a package‑private method and a test that demonstrates the transaction is not opened.

@Component
public class TestServiceImpl {
    @Resource
    TestMapper testMapper;

    @Transactional
    void insertTestWrongModifier() { // not public
        int re = testMapper.insert(new Test(10,20,30));
        if (re > 0) {
            throw new NeedToInterceptException("need intercept");
        }
        testMapper.insert(new Test(210,20,30));
    }
}

Scenario 2 – Internal self‑call: Calling a @Transactional method from another method of the same class bypasses the proxy (the call goes through this), so the transaction is never created. The article provides a service that invokes its own transactional method and a JUnit test that confirms the rollback does not occur.

@Component
public class InvokcationService {
    @Resource
    private TestServiceImpl testService;

    public void invokeInsertTestWrongModifier() {
        // direct self‑call, no proxy
        testService.insertTestWrongModifier();
    }
}

Scenario 3 – Swallowing the exception: If a transactional method catches the exception and does not re‑throw it, Spring’s TransactionAspectSupport never sees the error, so the transaction is committed instead of rolled back. The article includes a method that catches Exception and a corresponding test.

@Transactional
public void insertTestCatchException() {
    try {
        int re = testMapper.insert(new Test(10,20,30));
        if (re > 0) {
            throw new NeedToInterceptException("need intercept");
        }
        testMapper.insert(new Test(210,20,30));
    } catch (Exception e) {
        System.out.println("i catch exception");
    }
}

The underlying Spring logic is then examined: during bean creation Spring scans for methods with @Transactional using BeanFactoryTransactionAttributeSourceAdvisor and AopUtils#canApply. Only public methods produce a non‑null TransactionAttribute, which leads to proxy creation. When a method is invoked, TransactionAspectSupport#invokeWithinTransaction obtains the attribute, starts a transaction, executes the method via reflection, and either commits or rolls back based on whether an exception propagates.

In summary, the three reasons for @Transactional ineffectiveness are non‑public visibility, internal method calls that skip the proxy, and catching exceptions inside the transactional method. Understanding Spring’s proxy‑based AOP and ensuring methods are public, called through a Spring bean, and let exceptions propagate will keep transaction management working correctly.

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.

JavaProxyaopdatabasespringSpringBoottransactional
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.