Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring TransactionTemplate: roll back a failed multi-row change

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

TransactionTemplate executes a callback within a transaction controlled by its transaction manager, allowing the application to mark the transaction for rollback.

Download Spring source kit

This lesson uses the downloadable source kit: Java 21, Spring Boot 4.0.8 and its managed Spring Framework 7 dependencies. The version is pinned for repeatable builds.

Check state after the failure

The failing batch inserts a valid receipt and then violates the positive-amount constraint. The test catches the translated database failure and checks that the table remains empty. Counting rows after the transaction ends is stronger evidence than checking that an exception was thrown.

A second path marks rollback-only without throwing. It also leaves the table empty. The callback’s apparent success is therefore not a promise of commit when transaction state explicitly requests rollback.

Local atomicity has a boundary

A JDBC transaction can group changes on the managed connection. It cannot un-send an email or retract an HTTP request already accepted by another system. Coordinate external side effects with durable state and idempotent processing rather than calling them an automatic database rollback.

The H2 fixture is local and uses one datasource transaction manager. Cross-database changes, distributed recovery and production isolation behavior remain separate lessons. The source demonstrates a small atomicity contract, not a distributed transaction service.

Checked source

Java
public void batchThatFails() {
    transactions.executeWithoutResult(status -> { add(1, 40); add(2, -7); });
}
public void rollbackOnly() {
    transactions.executeWithoutResult(status -> { add(3, 60); status.setRollbackOnly(); });
}

Test the boundary

Run mvn test in the source-kit directory. ReceiptBoundaryTest.databaseFailureRollsBackWholeBatch and rollbackOnlyDoesNotCommit checks the behavior described here. Java excerpts belong to the named source-kit classes; they are not independent source files unless the complete class is shown.

Costs and boundaries

A transaction retains connection and database state until completion. Long callbacks consume pool capacity and can extend lock lifetimes; do not perform slow remote work inside them without an explicit reason and bounded budget.

Common Mistakes

  • Check persisted state after rollback.
  • Do not treat an external HTTP operation as rollback-capable JDBC work.
  • Keep transaction callbacks short and bounded.

Read next

Transaction proxies, Spring JdbcTemplate: bound values and visible database constraints, Java JDBC isolation: uncommitted writes and separate sessions.

Extend this boundary

Continue with Spring transaction propagation: joined rollback and independent commit, Spring JPA entity lifecycle: managed changes and detached objects.

Continue with ownership and failure checks

Continue with Spring transaction rollback: checked failures commit unless a rule says otherwise.

Continue with Spring delivery contracts

Continue with Spring transactional outbox: commit a receipt and event row together.

spring
spring-boot
transactions
Storage details