See how Spring
@Transactionalactually behaves. Pick a propagation (REQUIRED,REQUIRES_NEW,NESTED, …) and watch which writes commit or roll back when an inner or outer method throws — then flip through isolation levels and see which read anomalies each one lets through. The two@Transactionalthings everyone gets wrong, made visible.
▶ Live demo · Propagation · Isolation · Run locally
@Transactional looks like one annotation but hides two deep, easy-to-misuse dials: propagation and isolation. The bugs they cause are the worst kind — silent. An audit row that vanishes on rollback, a "saved" record that isn't, a report that reads a value another transaction never committed. This shows the outcome of each choice instead of making you guess.
A scenario you'll recognize: placeOrder() (@Transactional) saves an order, then calls audit.log(). Pick log()'s propagation and toggle "audit throws" / "outer throws after audit", and watch which of the two writes survives:
REQUIRED(default) — one shared transaction; any failure rolls back everything (and once it's rollback-only, catching the exception can't save it).REQUIRES_NEW— suspends the caller, runs an independent transaction that commits on its own. The audit survives even if the outer transaction rolls back — the classic "log it no matter what".NESTED— a savepoint; a caught inner failure does a partial rollback and the outer still commits (needs a savepoint-capableDataSourceTransactionManager).SUPPORTS/NOT_SUPPORTED/MANDATORY/NEVER— join, suspend, require, or forbid an existing transaction (with the gotchas each implies).
Bonus gotcha the tool reminds you of: self-invocation bypasses the proxy — calling
this.log()inside the same bean ignores its@Transactionalentirely.
A matrix of the four standard levels against the three read anomalies — dirty read, non-repeatable read, phantom read — plus a concrete two-transaction (T1/T2) walkthrough for the level you pick, showing exactly when each anomaly can occur or is prevented.
open index.html # macOS
start index.html # Windows
python -m http.server 8000 # or serve → http://localhost:8000A teaching model — the propagation/isolation semantics match Spring and the SQL standard; the DB writes are illustrative. Great for building the mental model before you reach for TransactionTemplate or debug an UnexpectedRollbackException.
Ideas: add the no-transaction caller case (SUPPORTS/MANDATORY without a tx), read-only transactions, timeout/rollbackFor rules, an animated concurrent isolation timeline. PRs welcome.
If this untangled @Transactional for you, a ⭐ helps others find it.
MIT © dev48v