Я думаю, что преамбула моего варианта использования загромождает мою фактическую точку, поэтому я перезагружаюсь более кратко: почему я не могу @Version
взять генератор и позволить мне назначить ему последовательность, как я могу сделать для @Id
;что-то вроде этого
@Entity
@javax.persistence.SequenceGenerator(
name="SEQ_STORE",
sequenceName="my_sequence"
)
public class Store implements Serializable {
private Long version;
@Version @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
public Long getVersion() { return version; }
}
Но вы не можете сделать это в JPA или Hibernate.Hibernate реализует @Version
в виде простого увеличенного значения 0,1,2 ... (или отметки времени).Суть в том, что я рассматриваю это как простой и приемлемый вариант использования.Кто-нибудь знает, почему это невозможно реализовать в спецификации JPA или с помощью расширения Hibernate?
РЕДАКТИРОВАТЬ: В моем случае было характерно то, что я использую временную звездообразную схему, где интерфейсы Hibernate через представления и триггеры делаютфактическое сохранение / обновление / удаление в таблицах фактов / измерений.Таблицы измерений действуют как таблицы «log», поэтому снимок может выглядеть следующим образом из table_name:
ID ENTRY_VALUE TIME_START TIME_COMPLETE PARENT_IS
1 22 10/23/2003 1:38 10/23/2003 1:56 -1
1 23 10/23/2003 1:56 10/23/2003 2:00 22
1 24 10/23/2003 2:00 10/23/2003 2:04 24
Что бы Hibernate увидел, это представление, основанное на этом sql
create view domain_object as select ... from table_name t inner join fact_table f on f.id = t.id where t.time_complete is null
Так что3 строки выше представляют жизненный цикл объекта домена с идентификатором 1. Он был создан в entry_value 22, обновлен в 23 и удален в 24. Если я использовал entry_value в качестве @Version
, то когда я добавляю другой объект домена, скажем, с ID 2, тогда versionчисла начинаются так:
ID ENTRY_VALUE TIME_START TIME_COMPLETE PARENT_IS
1 0 10/23/2003 1:38 10/23/2003 1:56 -1
1 1 10/23/2003 1:56 10/23/2003 2:00 22
1 2 10/23/2003 2:00 10/23/2003 2:04 24
2 0 10/23/2003 2:40 null 24
В этом случае PARENT_IS недопустим, нам нужно создать еще один столбец для размещения отношения PARENT_IS.
Итак, моя конечная точка в том, что когда Hibernate делает обновление, оно выглядит следующим образом
update table_name set column_name = 10, version_col_name = 2 where column_name = 3 and version_col_name = 1
Проверка версии и последующее обновление - это две семантически разностные операции, для оптимистической блокировки все запросы, о которых заботитсянаходя version_col_name = 1
, если этого не существует, мы получаем OptimisticLockException
.Обновление version_col_name путем увеличения его на 1 является полностью вторичным по отношению к оптимистическому акту блокировки и становится релевантным для последующего обновления.Поэтому в моем случае я хотел бы реализовать @Version
с последовательностью, поскольку в моем случае использования не происходит непрерывного обновления одной строки, как это обычно.