JPA оптимистическая блокировка с помощью SQLServer TIMESTAMP
Я пытаюсь настроить JPA оптимистическую блокировку на SQLServer. Для этого я использую TIMESTAMP
столбец (SQLServer TIMESTAMP
является инкрементным числом и не сохраняет дату или время).
Будучи автоматически увеличивающимся числом, на моем объекте Java мне нужно установить для вставляемого / обновляемого значения false
в противном случае я бы получил исключение:
com.microsoft.sqlserver.jdbc.SQLServerException: не удается обновить столбец отметки времени
Вот мое сопоставление сущностей Java:
@Version
@Column(name = "TSROWVERSION", insertable = false, updatable = false)
private byte[] version;
Когда я обновляю запись, этот SQL выполняется:
(1) *SELECT ... FROM cmd_e_entities WHERE uidentity=?*
(2) *UPDATE cmd_e_entities SET... WHERE uidentity=?*
но я ожидал получить что-то вроде:
(3) *UPDATE cmd_e_entities SET... WHERE uidentity=? AND tsrowversion=?*
Hibernate выполняет первый SELECT
проверить, изменилась ли запись (1), а затем она обновляется (2). Если запись была изменена, она выдает исключение:
org.hibernate.StaleObjectStateException: строка была обновлена или удалена другой транзакцией
Так что все работает нормально, но я ожидал UPDATE
принять во внимание версию (3). На самом деле, если изменить тип SQL от TIMESTAMP
в NUMBER
и удалите вставляемый / обновляемый, он работает как положено.
Если UPDATE
не считает версию (... AND tsrowversion=?
) как можно гарантировать оптимистическую блокировку? Как я могу получить мое ожидаемое поведение?
1 ответ
Hibernate проверяет, что версия объекта в памяти совпадает с сохраненной. Идентификатор объекта не меняется, кроме того, в Hibernate хранится только одна версия объекта, поэтому нет необходимости "фильтровать" по столбцу версий. Может быть, это JPA и оптимистичные режимы блокировки могут помочь