← All articles
Backend1 min read

Understanding @Transactional in Spring

Declarative transactions are convenient until they surprise you. Here's how propagation, rollback rules, and proxying actually work.

S

Swapnika Voora

Author

@Transactional wraps a method in a database transaction that commits on success and rolls back on failure. It's simple to add but has sharp edges around proxying, propagation, and which exceptions trigger a rollback.

The basic contract

Annotate a service method and Spring opens a transaction before it runs, then commits when it returns normally.

AccountService.java
@Service
public class AccountService {
 
    @Transactional
    public void transfer(Long from, Long to, BigDecimal amount) {
        accounts.debit(from, amount);
        accounts.credit(to, amount);
    }
}

If credit throws, the debit is rolled back — the transfer is all-or-nothing.

Rollback rules surprise people

By default Spring only rolls back on unchecked exceptions. A checked exception commits unless you say otherwise.

rollback.java
@Transactional(rollbackFor = IOException.class)
public void importFile(Path path) throws IOException {
    // now an IOException also triggers rollback
}

Propagation controls nesting

REQUIRES_NEW suspends the current transaction and runs in its own — useful for audit logs that must persist even if the outer transaction rolls back.

AuditService.java
@Service
public class AuditService {
 
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void log(String action) {
        auditRepo.save(new AuditEntry(action));
    }
}

The proxy gotcha

Like @Async, @Transactional works through a proxy. Calling a transactional method from another method in the same class skips the proxy entirely.

Takeaways

  • Only unchecked exceptions roll back by default — set rollbackFor otherwise.
  • Use REQUIRES_NEW for work that must commit independently.
  • Self-invocation bypasses the proxy, so the annotation is ignored.

When in doubt, keep transactions short and scoped to a single service method.

#java#spring-boot#transactions#jpa

More in Backend