skip to content

TransactionTemplate

TransactionTemplate wraps a callback in a transaction, rolling back on an unchecked exception or when you call setRollbackOnly, with per-call tuning of the definition. The standard answer when you want a transaction around part of a method instead of all of it.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is Spring's TransactionTemplate and when would you reach for it instead of @Transactional?

level: juniorimportance: must knowfreq 55%

answer

  1. Programmatic vs declarative (@Transactional)
  2. Wraps PlatformTransactionManager, is a TransactionDefinition
  3. execute / executeWithoutResult
  4. Commit on return, rollback on unchecked
  5. Use when only part of method / dynamic / no proxy

basics

~20 s

TransactionTemplate runs a block of code inside a database transaction programmatically. You call execute() and pass a callback; Spring starts a transaction, runs your code, then commits or rolls back. Use it when you need transaction control in code rather than the @Transactional annotation.

solid answer

~40 s

TransactionTemplate is Spring's helper for programmatic transaction management. You construct it with a PlatformTransactionManager, then call execute(TransactionCallback) or executeWithoutResult(Consumer<TransactionStatus>); Spring begins a transaction, runs your callback, and commits on normal return or rolls back on a thrown unchecked exception. It's the imperative alternative to declarative @Transactional. Reach for it when you need transactions around only part of a method, want to vary transaction settings dynamically, need fine-grained control over commit/rollback boundaries (for example wrapping just the DB write while leaving remote calls outside), or are in a context where AOP proxies don't apply (like a self-invocation or a plain non-bean object). It removes annotation/proxy 'magic' at the cost of more boilerplate.

code

java · 26 lines
java
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

public class AccountService {

    private final TransactionTemplate txTemplate;
    private final AccountRepository accounts;

    public AccountService(PlatformTransactionManager txManager, AccountRepository accounts) {
        this.txTemplate = new TransactionTemplate(txManager);
        this.accounts = accounts;
    }

    public Long openAccount(String owner) {
        // Runs inside a transaction; commits on normal return, rolls back on RuntimeException.
        return txTemplate.execute(status -> {
            Account a = accounts.save(new Account(owner));
            return a.getId();
        });
    }

    public void deposit(Long id, long cents) {
        // Void variant (Spring 5.2+): no need to return null.
        txTemplate.executeWithoutResult(status -> accounts.addBalance(id, cents));
    }
}

go deeper

for a junior

Know it runs code in a transaction via execute(), commits on success, rolls back on exception — the imperative counterpart to @Transactional.

for a middle

Explain the two entry points, that it wraps a PlatformTransactionManager, and give a concrete reason to prefer it over the annotation (partial method, dynamic settings, no proxy).

for a senior

Discuss proxy-boundary limitations of @Transactional that push you to programmatic control, and that the template is itself a TransactionDefinition.

for a principal

Weigh readability/testability trade-offs of programmatic vs declarative across a codebase; when a consistent policy should mandate one style.

## What it is `TransactionTemplate` (package `org.springframework.transaction.support`) is Spring's implementation of the *template method* pattern for **programmatic transaction management** — you write Java/Kotlin code that explicitly demarcates a transaction, instead of relying on the `@Transactional` annotation (which Spring implements with AOP proxies). Spring offers two ways to manage transactions: - **Declarative** — annotate a method with `@Transactional`. A proxy wraps the bean and opens/commits the transaction around the call. Low boilerplate, but only works through the proxy and applies to the whole method. - **Programmatic** — call an API in your own code. Two options exist: the low-level `PlatformTransactionManager` (manual `getTransaction`/`commit`/`rollback`), or the higher-level `TransactionTemplate` which handles the boilerplate for you. ## Core mechanism `TransactionTemplate` wraps a `PlatformTransactionManager` (e.g. `DataSourceTransactionManager` for JDBC, `JpaTransactionManager` for JPA). It **is itself a `TransactionDefinition`** (it extends `DefaultTransactionDefinition`), so propagation, isolation, timeout, and read-only settings are configured on the template. When you call: ```java template.execute(status -> { ... return result; }); ``` Spring does this internally: 1. Ask the transaction manager to start (or join) a transaction based on the template's definition. 2. Invoke your `TransactionCallback.doInTransaction(status)`. 3. If it returns normally → **commit**. 4. If it throws a `RuntimeException` or `Error` → **roll back**, then rethrow. 5. The result you return from the callback is returned from `execute`. ## The two entry points - `<T> T execute(TransactionCallback<T> action)` — returns a value. - `void executeWithoutResult(Consumer<TransactionStatus> action)` — added in **Spring 5.2**, for the common void case so you don't have to `return null`. ## When to use it - **Partial-method transactions** — you want only a slice of the method transactional (e.g. commit the DB write early, then do a slow non-transactional remote call). - **Dynamic settings** — you decide propagation/isolation/timeout at runtime. - **No proxy available** — inside a self-invoked private method, a plain object that isn't a Spring bean, or a lambda/callback where the `@Transactional` proxy boundary was already crossed. - **Explicit control** — teams that prefer visible transaction boundaries over annotation 'magic'. ## Gotchas - You still need a configured `PlatformTransactionManager` bean. - Rollback is on **unchecked** exceptions by default (checked-exception nuances differ from `@Transactional` — see the rollback question). - The template instance is **thread-safe to share** once configured, but you must not mutate its definition after publishing it. ## When NOT to use it For whole-method, static transaction boundaries `@Transactional` is cleaner and the idiomatic default. Use `TransactionTemplate` when declarative doesn't fit.

  • Does TransactionTemplate replace the need for a PlatformTransactionManager?
    No. TransactionTemplate is a thin convenience layer on top of a PlatformTransactionManager — you must still configure a transaction manager bean (e.g. JpaTransactionManager) and pass it to the template's constructor. The template just handles the begin/commit/rollback boilerplate for you.
  • Can @Transactional and TransactionTemplate coexist?
    Yes. They share the same underlying transaction manager and infrastructure. A TransactionTemplate call with default PROPAGATION_REQUIRED will join an already-active @Transactional transaction rather than start a new one, because propagation is honored across both styles.

saying these in an interview costs you the question

  • Thinking TransactionTemplate is a replacement for the transaction manager rather than a wrapper around it
  • Claiming it can only be used outside Spring-managed beans
  • Believing it always starts a brand-new transaction regardless of propagation

context

open as a page

What are the exact rollback rules for TransactionTemplate — which exceptions roll back, and how does setRollbackOnly() differ from throwing?

level: seniorimportance: must knowfreq 50%

basics

~10 s

If your callback throws a RuntimeException or Error, TransactionTemplate rolls back and rethrows. If it returns normally, it commits. You can also force rollback without throwing by calling status.setRollbackOnly() and returning normally.

open as a page

Explain TransactionTemplate.execute(TransactionCallback) versus executeWithoutResult, and what TransactionCallback / TransactionStatus give you.

level: middleimportance: should knowfreq 40%

basics

~20 s

execute() takes a TransactionCallback that returns a value, and hands it a TransactionStatus you can use (e.g. to mark rollback). executeWithoutResult() is a Spring 5.2 convenience for void work — it takes a Consumer<TransactionStatus> so you don't return null.

open as a page

How do you tune propagation, isolation, timeout and read-only on a TransactionTemplate for a specific unit of work, and what's the correct way to have multiple different settings?

level: seniorimportance: should knowfreq 35%

basics

~20 s

TransactionTemplate is itself a TransactionDefinition, so you configure propagation, isolation, timeout, and read-only on the template with setters like setPropagationBehavior, setIsolationLevel, setTimeout, setReadOnly. For different settings, create separate template instances rather than mutating a shared one.

open as a page

Is TransactionTemplate thread-safe, and how does that shape how you construct, share, and reuse it — including choosing it over @Transactional at scale?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Yes — once fully configured, a TransactionTemplate is thread-safe and meant to be shared as a single instance (typically a Spring bean). The catch: never change its settings after publishing it, because the definition fields aren't safe to mutate concurrently.

open as a page