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 и оптимистичные режимы блокировки могут помочь

Другие вопросы по тегам