Отсоединенный объект JPA не получает поле версии, заполненное

Я использую Roo 1.2.1, JPA 2 и Hibernate 3.6, подключенные к базе данных MSSQL.

У меня есть веб-сервис, который принимает JSON и анализирует его в сущности; очевидно, столбец @Version будет равен 0, потому что человек, вызывающий службу, ничего не знает об этом. Когда я вызываю merge() в первый раз, он работает нормально. Объект сохраняется правильно, и столбец версии устанавливается в 1. Но в следующий раз, когда я вызываю веб-сервис с теми же данными, он говорит, что объект устарел, что технически правильно, так как версия всегда будет 0.

Идентификатор, который они нам передают, гарантированно будет уникальным, поэтому мы используем его в качестве основного ключа.

Я хотел бы думать, что об этом позаботится менеджер организации.

Итак, мой вопрос: как мне справиться с этим, не загружая сначала все сущности из базы данных, затем обновляя поля, а затем повторно сохраняя их? Это похоже на взлом; может я об этом неправильно говорю?

Моя сущность выглядит так:

@RooJavaBean
@RooToString
@RooJson
@RooJpaActiveRecord(table = "MYTABLE", persistenceUnit = "myPersistenceUnit",
    transactionManager = "myTransactionManager", versionField = "version", identifierColumn = "myIdField")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Entity
public class MyEntity {
  @Id
  @Column(name = "myIdField")
  private long myIdField;

  @Version
  @Column(name = "version")
  private long version;

  @Column("myColumn")
  private String someValue;
}

1 ответ

Решение

Вы должны решить, хотите ли вы оптимистическую блокировку или нет.

Если вы хотите обновить базу данных тем, что отправляет клиент, независимо от возможных одновременных обновлений между временем получения объекта и временем его обновления, это означает, что вам не нужна оптимистическая блокировка, и не должно быть поле версии в объекте.

Если вы хотите оптимистическую блокировку, то версия должна быть частью объединенной сущности. Вот как работает механизм: он проверяет, совпадает ли сохраненный номер версии с переданным номером версии. Так что, если вы всегда передаете 0, очевидно, это никогда не сработает.

Самым простым способом является, конечно, сделать его частью объекта JSON, отправляемого клиенту и от него. Вы могли бы также представить сохранение версии данного объекта (отправленного клиенту для будущего обновления, поэтому ключом будет clientId-entityId) в некоторой таблице в памяти или в базе данных, но это будет сложнее реализовать.

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