java
persistence_error
ai_generated
true
javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction
ID: java/optimistic-lock-exception
85%Fix Rate
88%Confidence
70Evidence
2010-01-01First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 17 | active | — | — | — |
Root Cause
Another transaction modified the same entity between read and write. The @Version field doesn't match, so JPA/Hibernate rejects the update to prevent lost updates. Common in high-concurrency scenarios.
genericWorkarounds
-
90% success Implement retry logic that re-fetches the entity before each attempt
int retries = 3; while (retries-- > 0) { try { Entity e = repository.findById(id).orElseThrow(); e.setField(newValue); repository.save(e); break; } catch (OptimisticLockException ex) { if (retries == 0) throw ex; } } -
88% success Use pessimistic locking for high-contention entities
@Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT e FROM Entity e WHERE e.id = :id") Optional<Entity> findByIdForUpdate(@Param("id") Long id);Sources: https://docs.spring.io/spring-data/jpa/reference/jpa/locking.html
Dead Ends
Common approaches that don't work:
-
Removing the @Version field to disable optimistic locking
80% fail
Removes the safety mechanism that prevents lost updates. Concurrent modifications will silently overwrite each other, causing data corruption.
-
Catching the exception and blindly retrying the same update
90% fail
Retrying with the same stale data will hit the same version conflict. The entity must be re-fetched before retrying.
Error Chain
Frequently confused with: