Spring Row was updated or deleted by another trans

2019-08-30 02:30发布

问题:

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.

回答1:

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.