The save that is never flushed
A hard Java puzzle in the spring pitfalls family. One line below contains a real bug. Try to spot it first, then read why it fails and how to fix it.
Highlighted: line 10. Play this one as a puzzle without the answer.
What is wrong
readOnly = true tells Hibernate not to flush at commit, so the dirty change to the entity is never written. Depending on the database and driver it may also be rejected. The method returns normally and the rename silently does nothing.
The fix
How to avoid it next time
Use readOnly = true only on methods that do not write. Check the actual SQL when something "does not save".
Want the background? Read @Transactional in the Java concepts library.
About spring pitfalls
Spring features such as @Transactional, @Async and @Cacheable work through proxies. Calls that bypass the proxy, wrong bean scopes and misplaced annotations make behavior silently disappear.
In code review: For every annotation that adds behavior, check that the call crosses a Spring-managed bean boundary, that the method is public, and that the bean is a singleton only when it is stateless.
More puzzles in this family
Frequently asked questions
What is the bug in "The save that is never flushed"?
readOnly = true tells Hibernate not to flush at commit, so the dirty change to the entity is never written. Depending on the database and driver it may also be rejected. The method returns normally and the rename silently does nothing. The faulty line is line 10: @Transactional(readOnly = true)
How do I fix it?
Replace it with: @Transactional public void rename(long id, String name) { ... }. Use readOnly = true only on methods that do not write. Check the actual SQL when something "does not save".
How do I catch spring pitfalls in code review?
For every annotation that adds behavior, check that the call crosses a Spring-managed bean boundary, that the method is public, and that the bean is a singleton only when it is stateless.
Is there a new puzzle every day?
Yes. The daily Spot the Bug puzzle picks one of these snippets for each UTC day, with the difficulty set by the weekday. Your streak is stored only in your browser.