I am saving objects using Spring Data JPA save(Object entity) method from a multi-threaded web application.
Occasionally I find that when I load an object from the session using:
The object returned from the session is stale and doesn't reflect the latest version from the database. I am ONLY saving data from this application and ONLY using one instance of Spring Data JPA interface.
What could be causing it and how should I fix this?
Hibernate uses the PreparedStatement#executeUpdate result to check the number of updated rows. If no row was matched, it then throws a StaleObjectStateException (when using Hibernate API) or an OptimisticLockException (when using JPA).
Optimistic locking is a generic-purpose concurrency control technique, and it works for both physical and application-level transactions.
So the stale exceptions prevent the "lost update" phenomena when multiple concurrent requests modify the same shared persistent data.
In an application-level transaction, once you load an entity you will get a logical repeatable read due to 1st level cache (Persistence Context), but other users can still modify the aforementioned entity.
So you can indeed run into stale entities, but the optimistic locking mechanism prevents loosing updates without taking any additional database locks, and it even works for long conversations.