Spring Row был обновлен или удален другой транзакцией (или отображение несохраненных значений было неверным)
Я не могу понять, что не так с моей службой. я получил org.hibernate.StaleObjectStateException
пытаясь запустить этот метод:
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?
}
Клиентский объект:
@Entity
data class Client(
var name: String = "",
var phone: String = "",
@Id @GeneratedValue(strategy = GenerationType.AUTO)
val uuid: UUID = defaultUuid()
)
Исключение:
Объект класса [com.app.modules.client.domain.Client] с идентификатором [12647903-7773-4f07-87a8-e9f86e99aab3]: сбой оптимистической блокировки; вложенное исключение - org.hibernate.StaleObjectStateException: строка была обновлена или удалена другой транзакцией (или сопоставление несохраненного значения было неправильным): [com.app.modules.client.domain.Client#12647903-7773-4f07-87a8-e9f86e99aab3]"
Какова причина? Я использую Kotlin 1.3.11, Spring Boot 2.1.1, MySql. Я не запускаю его в разных потоках, просто пробую одним запросом.
1 ответ
Ну наконец-то я нашел решение. Лучше сказать обходной путь.
Проблема в том, как весна использует UUID
в качестве идентификатора объекта. Таким образом, есть два обходных пути, решающих эту проблему:
- во-первых, вы можете изменить тип поля id на другой, например
Long
например, если это возможно для вас; - или вы можете добавить эту аннотацию к вашему
uuid
поле:@Column(columnDefinition = "BINARY(16)")
,
Последнее решение, которое я нашел из этого вопроса.