With nested REQUIRED calls, what is shared between the outer and inner methods, and what is the difference between a physical and a logical transaction?
answer
- Physical = DB's BEGIN/COMMIT
- Logical = each @Transactional scope
- Outermost begins & commits
- Inner attrs (isolation/timeout/readOnly) ignored
- One Connection = one persistence context
basics
~20 sThey share one physical transaction and one JDBC Connection. Each @Transactional method is a separate logical scope, but nested REQUIRED scopes all map onto the single physical transaction, so they commit or roll back together.
solid answer
~40 sREQUIRED creates one physical transaction — one Connection with autoCommit off, bound to the thread — and every nested REQUIRED method participates in it as a logical transaction. The physical transaction is what the database sees: a single BEGIN...COMMIT. Logical transactions are Spring's bookkeeping for each @Transactional boundary entered. Only the outermost call actually begins and commits the physical transaction; inner participants just mark entry and exit. Attribute overrides like timeout, isolation, or read-only that you put on an inner REQUIRED method are effectively ignored, because there's no new physical transaction to apply them to (Spring can warn or throw for isolation mismatches). The practical consequence: because there's one Connection and one commit point, the whole nested call graph is atomic.
code
java · 18 lines@Service
public class BillingService {
@Transactional // outermost REQUIRED -> starts the physical transaction
public void checkout(Cart cart) {
charge(cart);
audit(cart); // joins the SAME physical tx/Connection
}
@Transactional(timeout = 2) // <-- timeout here is IGNORED: not a new physical tx
public void audit(Cart cart) {
// shares checkout()'s Connection and persistence context
}
// @Transactional(isolation = SERIALIZABLE) on a nested REQUIRED method would
// throw IllegalTransactionStateException if it differs from the active tx.
void charge(Cart cart) { /* ... */ }
}go deeper
Grasp that nested REQUIRED calls share one transaction.
Articulate physical vs logical and that only the outermost begins/commits.
Explain why inner attribute overrides are ineffective and when that forces REQUIRES_NEW.
Use the physical/logical model to reason about connection usage, persistence-context scope, and pool pressure across a call graph.
## Physical vs logical transaction Spring deliberately separates two notions: - **Physical transaction** = the real database transaction. One `Connection`, `autoCommit=false`, a single `BEGIN ... COMMIT/ROLLBACK` as far as the DB is concerned. Managed by the `PlatformTransactionManager`. - **Logical transaction** = each `@Transactional` scope your code enters. It's Spring-side bookkeeping. With REQUIRED, nested logical transactions all **share one** physical transaction. Analogy: the physical transaction is the building; each logical transaction is a person walking in and out. The building's doors (BEGIN/COMMIT) open only when the *first* person enters and close when the *last* leaves. ## What is shared When `outer()` (REQUIRED) calls `inner()` (REQUIRED): - **The same Connection** — bound to the thread by `TransactionSynchronizationManager`. Every repository/`JdbcTemplate`/JPA `EntityManager` on that thread uses it. - **The same physical transaction** — one commit, one rollback boundary. - **The same persistence context** in JPA (the `EntityManager` is thread-bound too), so entities loaded in `outer()` are managed and visible in `inner()`. ## Who begins and commits Only the **outermost** REQUIRED scope calls `getTransaction()` that actually starts a physical transaction, and only its return path triggers the real commit. Inner participants get a transaction status flagged as 'not new' — their 'commit' is a no-op on the physical transaction; their 'rollback' instead marks the shared transaction **rollback-only** (see the rollback-only question). ## Attribute overrides on inner methods Because the inner REQUIRED method doesn't open a new physical transaction, transaction-scoped attributes you set there are largely ineffective: - **isolation**: by default Spring **throws** `IllegalTransactionStateException` if an inner REQUIRED method declares an isolation that differs from the active transaction, unless `validateExistingTransaction` is off (then it's silently ignored). - **timeout**: the inner value is ignored; the outer transaction's timeout governs. - **read-only**: the inner `readOnly=true` doesn't relax or tighten the already-running transaction. The lesson: set isolation/timeout/read-only at the boundary that actually **starts** the transaction. ## Why one Connection matters Because there's a single Connection, you cannot have the inner method 'independently commit' — its writes are invisible to other DB sessions until the outer commit, and a failure anywhere poisons the whole thing. If you genuinely need an independent commit (e.g. write an audit row that survives an outer rollback), you must switch that method to `REQUIRES_NEW`, which suspends the current transaction and borrows a second Connection. ## When to care This model is exactly what you want for a cohesive unit of work. You only need to think hard about it when: (a) you want partial commits, (b) you're tempted to set isolation/timeout on an inner method, or (c) you're chasing an `UnexpectedRollbackException`.
- If you set @Transactional(timeout = 2) on an inner REQUIRED method, does it take effect?No. There's no new physical transaction, so the inner timeout is ignored; the outermost transaction's timeout applies.
- What happens if an inner REQUIRED method declares a different isolation level than the outer?By default Spring throws IllegalTransactionStateException (validateExistingTransaction). Isolation must be set where the physical transaction begins.
saying these in an interview costs you the question
- Claiming each nested @Transactional gets its own Connection or commits independently.
- Thinking inner isolation/timeout/read-only overrides take effect under REQUIRED.
- Assuming an inner method can commit its work while the outer later rolls back.