Card 03/ 07
All 7 cards
GotchaDifficulty: Advanced1 min
The Exception That Doesn't Roll Back
Two methods, each saving a row and then throwing. One rolls the save back. The other doesn't — the row is still there afterward.
@Transactional
void insertThenThrowUnchecked() {
repo.save(new LedgerEntity("unchecked-attempt"));
throw new RuntimeException("boom - unchecked");
}
@Transactional
void insertThenThrowChecked() throws MyCheckedException {
repo.save(new LedgerEntity("checked-attempt"));
throw new MyCheckedException("boom - checked");
}after UNCHECKED exception, row count = 0
after CHECKED exception, row count = 1Spring's default rollback rule: an unchecked exception (RuntimeException or Error) rolls the transaction back; a checked exception does not, and the transaction commits on its way out. This traces back to Spring's own convention, not the database's — checked exceptions were historically treated as expected, recoverable outcomes, and an expected outcome doesn't undo work. Throwing a checked exception from inside a @Transactional method and assuming it behaves like any other failure is exactly how a half-finished operation quietly commits.