How does REQUIRES_NEW differ from Propagation.NESTED?
answer
- REQUIRES_NEW = new connection, independent commit
- NESTED = savepoint, same connection
- Outer rollback: kills NESTED, spares REQUIRES_NEW
- JPA usually can't do NESTED
- NESTED not durable until outer commits
basics
~20 sREQUIRES_NEW is a fully independent transaction on its own connection that commits separately. NESTED is a savepoint inside the same transaction and connection — rolling it back undoes only to the savepoint, but it commits only when the outer transaction commits.
solid answer
~40 sBoth let an inner unit of work fail without necessarily failing the caller, but the mechanisms differ. REQUIRES_NEW **suspends** the outer transaction and starts a **separate physical transaction on a second connection**; it commits or rolls back fully independently, so its committed data survives an outer rollback. NESTED runs on the **same connection** as the outer transaction by creating a JDBC **savepoint** (`Connection.setSavepoint`). Rolling back the nested part only rolls back to the savepoint, leaving earlier outer work intact — but the nested changes are **not durable until the outer transaction commits**; if the outer rolls back, the nested work is lost too. NESTED requires JDBC savepoint support and `DataSourceTransactionManager` (JPA/Hibernate generally doesn't support it). Use REQUIRES_NEW for true independence (audit rows); use NESTED for partial rollback within one atomic outer transaction.
code
java · 19 lines// REQUIRES_NEW — audit survives outer rollback
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void audit(String msg) { /* separate connection, own commit */ }
// NESTED — savepoint inside the SAME outer transaction
@Transactional
public void processBatch(List<Item> items) {
for (Item i : items) {
try {
processOne(i); // NESTED: bad item rolls back to savepoint only
} catch (Exception e) {
log.warn("skipping {}", i.getId()); // batch continues
}
}
// Everything durable only when THIS outer tx commits.
}
@Transactional(propagation = Propagation.NESTED)
public void processOne(Item i) { /* same connection + savepoint */ }go deeper
May not know NESTED exists; that's acceptable.
Should contrast independent-commit vs savepoint and the outer-rollback behavior.
Should note connection usage, JPA's lack of NESTED support, and correct use cases.
Should discuss savepoint cost, driver support, and designing for partial-failure semantics.
## The two mechanisms ### REQUIRES_NEW - Starts a **completely independent** transaction. - **Suspends** the outer transaction and obtains a **new `Connection`**. - Commit/rollback of the inner tx is **atomic and durable on its own**, independent of the outer. - After an inner commit, that data is persisted even if the outer later rolls back. ### NESTED (Propagation.NESTED) - Runs **inside the same physical transaction and on the same `Connection`** as the outer. - Implemented with a **JDBC savepoint**: `AbstractPlatformTransactionManager` (via `JdbcTransactionObjectSupport`/`SavepointManager`) calls `connection.setSavepoint()` when the nested block begins. - On failure, only a **`rollbackToSavepoint`** happens — work done *before* the savepoint in the outer tx is preserved, but nested work is undone. - On success, nothing is committed yet; the nested changes become durable **only when the single outer transaction commits**. If the outer rolls back, everything (including the nested part) is lost. ## Side-by-side | Aspect | REQUIRES_NEW | NESTED | |---|---|---| | Connection | New, separate | Same as outer | | Outer during inner | Suspended | Still active | | Independent commit? | Yes | No — commits with outer | | Inner rollback affects outer? | No | No (only to savepoint) | | Outer rollback affects inner? | No (already committed) | Yes — undoes nested too | | Survives outer rollback? | Yes | No | | Mechanism | Two transactions | Savepoint in one tx | | Extra connection used? | Yes (two at once) | No | ## Support & gotchas - **NESTED requires savepoint support**: `DataSourceTransactionManager` with a JDBC driver that supports savepoints, and `nestedTransactionAllowed=true` (default for that manager). `JpaTransactionManager`/Hibernate typically **do not** support NESTED and throw `NestedTransactionNotSupportedException`. - **REQUIRES_NEW needs suspension support** (standard managers have it) and consumes a second connection — pool-pressure risk. - **Common confusion**: people reach for REQUIRES_NEW wanting 'partial rollback but same atomic unit' — that's actually NESTED. Conversely they use NESTED expecting the audit row to survive an outer rollback — it won't. ## When to use which - **REQUIRES_NEW**: the inner work must persist regardless of the caller's fate (audit/log/outbox, recording a failed-payment attempt). - **NESTED**: you want a checkpoint inside one atomic operation — e.g. try an optional sub-step, roll it back on error, but still commit or discard everything together with the main transaction (batch item processing where a bad item shouldn't kill the whole batch but the whole batch is still one commit).
- If you use NESTED to write an audit row and the outer transaction rolls back, does the audit row survive?No. NESTED shares the outer transaction and only becomes durable when the outer commits. An outer rollback discards the nested work too. For a surviving audit row you need REQUIRES_NEW.
- Why does NESTED often fail with JPA/Hibernate?NESTED relies on JDBC savepoints managed by DataSourceTransactionManager. JpaTransactionManager generally doesn't support savepoint-based nested transactions and throws NestedTransactionNotSupportedException.
saying these in an interview costs you the question
- Saying NESTED uses a separate connection
- Claiming NESTED-committed data survives an outer rollback
- Treating REQUIRES_NEW and NESTED as interchangeable
- Assuming JPA supports NESTED out of the box