Querieshard5-8 years
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?
A bulk @Modifying statement goes straight to the database; it does not pass through the persistence context, so Hibernate does not know which rows changed. The account was already managed in this transaction, and findById for a managed entity is answered from the first-level cache without touching the database, so it returns the stale object. clearAutomatically = true clears the persistence context after the statement so the next read loads fresh rows. flushAutomatically = true flushes pending changes before the statement. They are a pair: clearing without flushing first throws away any unflushed changes you had made to managed entities.
PreviousA `@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?Next `Category.products` is a `@OneToMany(mappedBy = "category")`, and someone adds `orphanRemoval = true` "for consistency" with `Order.lines`, which has it. The next day, an admin un-categorises a product (removes it from the category's collection and clears `product.category`), and the product row is deleted from the database. No `remove()` was called anywhere. Explain the difference between `CascadeType.REMOVE` and `orphanRemoval`, and why only one of them fired here.