data access

@Transactional

Run a unit of work atomically — all-or-nothing — with one annotation, deferring commit/rollback to Spring.

@Transactional lets you declare that a method runs as a single atomic unit of work — every database change inside it either commits together or rolls back together — without writing explicit begin/commit/rollback code. It turns transaction management from imperative boilerplate into a declarative concern, which is essential when one business operation touches several tables and a partial failure would leave the data inconsistent.

A bank transfer — either both debit and credit happen, or neither. The teller (proxy) handles the paperwork.

Key Concepts

1
Under the hood Spring wraps the annotated bean in a proxy. When a caller invokes the method, the proxy opens a transaction before the body runs, commits if it returns normally, and rolls back if it throws. Two attributes dominate its behaviour. Propagation controls what happens when a transactional method calls another: the default REQUIRED joins an existing transaction or starts one, while REQUIRES_NEW suspends the current one and runs in an independent transaction — important for things like audit logging that must persist even if the outer operation rolls back. Isolation maps to the database's isolation levels, trading consistency against concurrency. By default Spring rolls back on unchecked (runtime) exceptions but commits on checked ones, which surprises people; you override this with rollbackFor.
REQUIREDREQUIRES_NEWrollbackFor
2
The pitfalls here are a perennial interview favourite because they stem from the proxy mechanism. Self-invocation does not work: if a method calls another @Transactional method on this, the call bypasses the proxy and the annotation is ignored. By default the proxy only applies to public methods. And rollback only happens for runtime exceptions unless you say otherwise, so a caught-and-swallowed exception, or a checked exception you forgot to list, can silently commit a half-finished operation.
@Transactionalthis
3
What the interviewer is probing.
What the interviewer is probing.
4
1. "Why does @Transactional not work on a private or self-called method?" *Probing:* the classic. *Stalls:* "It does." *Moves up:* it is proxy-based, so only calls through the proxy are intercepted — an internal call bypasses it entirely.
1. "Why does @Transactional not work on a private or self-called method?"
5
2. "Which exceptions roll back by default?" *Probing:* the trap. *Stalls:* "All of them." *Moves up:* unchecked ones only — a checked exception commits unless rollbackFor says otherwise.
2. "Which exceptions roll back by default?"
6
3. "What does propagation REQUIRES_NEW do?" *Probing:* the detail. *Stalls:* "Starts a transaction." *Moves up:* suspends the current one and runs in a new independent transaction, which is how an audit row survives a rollback.
3. "What does propagation REQUIRES_NEW do?"
7
4. "What is the risk of a long transaction?" *Probing:* the operational angle. *Stalls:* "None." *Moves up:* it holds connections and locks — especially one spanning an HTTP call to another service, which should never happen.
4. "What is the risk of a long transaction?"