StaleObjectStateException: Row was updated or deleted by another transaction?

user2722142 picture user2722142 · Sep 3, 2013 · Viewed 33.8k times · Source

I do the following:

def currentUser = springSecurityService.currentUser
currentUser.name = "test"
currentUser.save(flush: true)

// some other code

currentUser.gender = "male"
currentUser.save(flush: true)        // Exception occurs

This is the exception I get:

ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

How can I prevent this error? What is the best solution for that?

I found different approaches:

  1. here that you can use discard()
  2. here that you can use merge()

Which one should I use?

Answer

Anuj Aneja picture Anuj Aneja · Sep 3, 2013

You should use merge - it will update the object to match the current state in the database. If you use discard it will reset the object back to what the database has, discarding any changes. Everything else in the hibernate session you need to manage yourself.

More importantly code should be written in a service so that there is a database transaction, and you should use

save(flush:true) 

once only at the end.

def currentUser = springSecurityService.currentUser
currentUser.name = "test"

//    currentUser.save(flush: true) // removing this line because if a rollback occurs, then changes before this would be persisted.


// some other code

currentUser.gender = "male"
currentUser.merge()                 // This will merge persistent object with current state
currentUser.save(flush: true)