Transaction Pitfalls (Part 4)

Multi-threaded Calls and Spring Transaction Mechanism

Problem Causes:

  1. Spring stores transaction state in ThreadLocal variables
  2. Newly created threads cannot access parent thread’s ThreadLocal variables
  3. Causing child threads to fail to inherit parent thread’s transaction context

Solutions:

  1. Avoid creating new threads in transaction methods
  2. Use programmatic transaction management
  3. Use distributed transaction framework (such as Seata)

Exception Catching and Spring Transaction Rollback Mechanism

Problem Cause:

  • When an exception is caught and handled within a method’s try-catch block, Spring’s transaction interceptor cannot perceive this exception

Solutions:

  1. Manually roll back transaction in catch block
  2. Re-throw the exception
  3. Configure rollbackFor attribute of @Transactional annotation
@Transactional
public void someMethod() {
    try {
        // Business code
    } catch (Exception e) {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

Manual Exception Throwing

Problem Cause:

  • Spring only rolls back transactions for RuntimeException and Error by default

Solutions:

  1. Configure rollbackFor rules
  2. Wrap checked exceptions and throw as runtime exceptions
@Transactional(rollbackFor = {IOException.class, SQLException.class})
public void businessMethod() throws IOException {
    // Business logic
}