Hibernate с последовательностью Oracle не использует его
Я настроил hibernate для использования последовательности oracle. Последовательность создается с кешем = 20, increment = 1.
Все работает нормально, спящие сохраняющиеся объекты. Значение id странно: 50,51.... 76,201,202... 209,1008,1009,5129,5130....
Если я запрашиваю значение последовательности (выберите hibernate_sequence.nextval из double), я получаю значение, как 2,3,4....
Если включить hibernate sql debug, то время от времени вызывается "select hibernate_sequence.nextval from dual", но число, назначенное спящим ID, не ретранслируется в последовательности!
@Id
@Column(name = "ID", insertable = false, updatable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private Long id;
Ответы
Ответ 1
Это потому, что генератор последовательности не является генератором последовательности. Это последовательность hi-lo-генератора. Это означает, что при первом вызове он получает следующее значение из последовательности (например, 6), а затем умножает это значение на 50 и дает результат (300). В следующий раз, когда он вызывается, он возвращает 301 (без перехода к последовательности) и так далее, пока не достигнет 349. Затем он запрашивает последовательность для следующего значения и получает 7, что умножает на 50, чтобы дать вам 350. Мой описание алгоритма может быть отключено одним, но вы получите эту идею.
Если вы остановите и запустите приложение, у него, таким образом, будут пробелы. Но он более эффективен, чем генератор чистой последовательности, поскольку он только вызывает вызов базы данных один раз в 50 поколений.
Смотрите http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizers и http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-generator для подробности.
Ответ 2
Я полагаю, что ваш вопрос в том, что значения столбца ID в базе данных не являются естественной последовательностью, но почему вы видите пробелы:
Немного фона:
- Каждый раз, когда вы вызываете
select HIBERNATE_SEQUENCE.nextval from DUAL
, значение последовательности увеличивается.
- Поскольку ваше имя последовательности является общим, а не специфичным для таблицы, если у вас есть несколько объектов, которые все используют HIBERNATE_SEQUENCE в качестве генератора идентификаторов, то значения из последовательностей используются во всех сущностях.
- Если какое-либо другое приложение использует HIBERNATE_SEQUENCE, значение также пропускается.
- Когда вы используете CACHE = 20, Oracle будет захватывать порядковые номера в блоках по 20, а затем использовать внутренний кеш для возврата чисел. Это может привести к тому, что числа будут пропущены, если кеш потерян (например, если БД выключено).
- Если строки удалены из вашей базы данных, значение последовательности не изменяется
Например, рассмотрим следующий сценарий:
У вас есть два объекта Entity1 и Entity2 с использованием HIBERNATE_SEQUENCE в качестве генератора идентификаторов:
- Текущее значение HIBERNATE_SEQUENCE равно 100
- Вставляется Entity1 (использует HIBERNATE_SEQUENCE, который возвращает 101)
- Вставляется Entity2 (использует HIBERNATE_SEQUENCE, который возвращает 102)
- Вставляется Entity2 (использует HIBERNATE_SEQUENCE, который возвращает 103)
- Entity2 с идентификатором 103 удаляется
- Вы выполняете вручную
select HIBERNATE_SEQUENCE.nextval from DUAL
(возвращает 104)
- Вставляется Entity1 (использует HIBERNATE_SEQUENCE, который возвращает 105)
- Вставляется Entity2 (использует HIBERNATE_SEQUENCE, который возвращает 106)
Итак, в конце вы получите:
- Entity1 с идентификаторами (101, 105)
- Entity2 с идентификаторами (102, 106)
который объясняет пробелы.
EDIT:
Даже если @SequenceGenerator был настроен на использование SequenceGenerator
, а не SequenceHiLoGenerator
(как указано JB Nizet, что, по моему мнению, является лучшим объяснением пробелов), пробелы в идентификаторах, генерируемых последовательностями, являются обычное явление.
Ответ 3
CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1;
grant all on SEQ_SEQUENCENAME to public;
@Id
@Column(name = "ID", unique = true, nullable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private int Id;