Transactionsmedium3-5 years
A `@Transactional` transfer debits one account and then throws a checked `InsufficientFundsException` from a later check. The caller catches it, and the money has moved anyway. Why did the transaction commit, and how do you make it roll back?
By default Spring rolls back only on unchecked exceptions (RuntimeException and Error). A checked exception is treated as a declared business outcome, so the proxy commits on the way out, and the debit that dirty checking noticed is written, even though the caller saw an exception. The fix is to say what you mean: @Transactional(rollbackFor = InsufficientFundsException.class) (or rollbackFor = Exception.class), or prefer unchecked exceptions for failures in a transactional service so you never meet this default.
PreviousAn entity's `equals`/`hashCode` are generated from its `@GeneratedValue` id. A new `Tag` is added to a `HashSet`, persisted, and then `set.contains(tag)` returns `false` — even though `set.size()` is 1 and iterating returns that exact object. Why, and what should an entity's `equals`/`hashCode` be based on?Next Inside one transaction, a service runs a repository `@Modifying @Query("update Account a set a.status = 'FROZEN' where a.owner = :owner")`, then calls `findById` on one of those accounts and still sees `ACTIVE`. The database says `FROZEN`. What happened, and what do `clearAutomatically` and `flushAutomatically` each fix?