Spring Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

12,064

Well, finally I've found a solution. Better say workaround.

The problem is in the way spring uses UUID as entity identifier. So there are two workarounds, solving this issue:

  • first, you can change your id field type to other one, such as Long, for example, if it's possible to you;
  • or you can add this annotation to your uuid field: @Column(columnDefinition = "BINARY(16)").

The last solution I've found from this question.

Share:
12,064

Related videos on Youtube

Kamo Spertsian
Author by

Kamo Spertsian

Team Lead at Profi.ru

Updated on June 04, 2022

Comments

  • Kamo Spertsian
    Kamo Spertsian almost 2 years

    I can't understand, what's wrong with my Service. I receive org.hibernate.StaleObjectStateException trying to run this method:

    fun updateNameForPhone(phone: String, name: String): Client {
        val res = clientRepository.findByPhone(phone) ?: throw ClientNotFoundException(phone)
    
        res.name = name
        return clientRepository.save(res)
    }
    

    ClientRepository:

    @Repository
    interface ClientRepository : JpaRepository<Client, UUID> {
    
        fun findByPhone(phone: String): Client?
    }
    

    Client entity:

    @Entity
    data class Client(
            var name: String = "",
            var phone: String = "",
            @Id @GeneratedValue(strategy = GenerationType.AUTO)
            val uuid: UUID = defaultUuid()
    )
    

    Exception:

    Object of class [com.app.modules.client.domain.Client] with identifier [12647903-7773-4f07-87a8-e9f86e99aab3]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.app.modules.client.domain.Client#12647903-7773-4f07-87a8-e9f86e99aab3]"

    What is the reason? I'm using Kotlin 1.3.11, Spring Boot 2.1.1, MySql. I don't run it in different threads, just trying with single request.

    • Ankur
      Ankur over 5 years
      can you share how have you defined the transaction here?
    • Ankur
      Ankur over 5 years
      Also, it would be helpful to have database table structure as well
    • Simon Martinelli
      Simon Martinelli over 5 years
      You get a optimistic lock exception but I don't see that you are using a version field. Can you please post the whole code?
    • Kamo Spertsian
      Kamo Spertsian over 5 years
      @simonmartinelli I have no version field, it has not yet been necessity.
    • Kamo Spertsian
      Kamo Spertsian over 5 years
      @ankur No transaction and table creations myself, it's incapsulated by Spring. I just tag my Client class with Entity annotation. Service method is called from Controller. There is no interesting code there.
    • Ankur
      Ankur over 5 years
      Here is what i think is the problem: clientRepository.findByPhone(phone) is taking place under transaction T1 while clientRepository.save(res) is taking place under transaction T2. since, your res object is part of 2 different transactions, you are facing this issue. Have you used @Transactional anywhere in your code?
    • Kamo Spertsian
      Kamo Spertsian over 5 years
      @Ankur Controller's method, which calls service method, is annotated as Transactional, but I've deleted this annotation from there and nothing've changed.
    • Kamo Spertsian
      Kamo Spertsian over 5 years
      The problem disappears when I change the table identifier type from UUID to Long.. Looks like something is wrong with UUID and Spring communication.. Btw Long ids are not suitable for me, so I am trying to solve this problem.