Почему спецификация JPA (включая 2.0) или расширение Hibernate не позволяет указать генератор, например Последовательность Oracle для аннотации @Version - PullRequest
0 голосов
/ 02 октября 2009

Я думаю, что преамбула моего варианта использования загромождает мою фактическую точку, поэтому я перезагружаюсь более кратко: почему я не могу @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 с последовательностью, поскольку в моем случае использования не происходит непрерывного обновления одной строки, как это обычно.

Ответы [ 2 ]

2 голосов
/ 02 октября 2009

Я не знаю, почему вы видите это как простой и приемлемый вариант использования. Номер версии увеличивается каждый раз, когда объект обновляется, и используется, чтобы избежать одновременных изменений. Почему последовательность будет лучше для этого? В чем проблема с использованием 0 в качестве начального значения? Зачем вам нужен порядковый номер (следующее значение) вместо 0 при создании нового экземпляра? Какой смысл?

1 голос
/ 02 октября 2009

Я все еще не до конца уверен в том, что вы пытаетесь сделать, поэтому, пожалуйста, прокомментируйте, если то, что я предлагаю, не соответствует тому, что вы имели в виду.

Hibernate допускает , что версия может быть основана на последовательности, хотя это не очень просто:

Вам необходимо пометить свойство "version" как сгенерированное , что вы можете сделать с помощью Расширения аннотации Hibernate , и вы можете сгенерировать его в своей базе данных с помощью любых необходимых средств. в том числе принимая его значение из последовательности.

Тем не менее, ваш вариант использования, хотя и вполне приемлемый (потому что он существует), не является ни простым, ни распространенным. Я не уверен, почему вам даже нужна оптимистическая блокировка, поскольку кажется, что вы пытаетесь сохранить всю историю изменений сущностей и, следовательно, предположительно делаете только вставки (хотя, возможно, я неправильно понял ваше объяснение).

...