Отсоединенный объект 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) в некоторой таблице в памяти или в базе данных, но это будет сложнее реализовать.