Спящий режим с последовательностью Oracle не использует его

Я настроил спящий режим для использования последовательности оракула. Последовательность создается с кэшем=20, приращением=1.

Все работает нормально, спящий режим сохраняется. Значение идентификатора странное: 50,51....76,201,202...209,1008,1009,5129,5130....

Если я запрашиваю значение последовательности (выберите hibernate_sequence.nextval из двойного), я получаю значение вроде 2,3,4....

Если я включаю отладку спящего режима sql, время от времени вызывается «выбрать hibernate_sequence.nextval из двойного», но номер, назначенный спящим режимом для идентификатора, не соответствует последовательности!

@Id
@Column(name = "ID", insertable = false, updatable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private Long id;

person Vlada    schedule 24.08.2011    source источник


Ответы (3)


Это связано с тем, что SequenceGenerator на самом деле не является генератором последовательности. Это генератор последовательности "привет-лоу". Это означает, что при первом вызове он получает следующее значение из последовательности (например, 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 для получения подробной информации.

person JB Nizet    schedule 24.08.2011
comment
Вам не нужно каждый раз увеличивать значение на 50. Это просто по умолчанию. Используйте @SequenceGenerator(name=SEQ_ID,sequenceName=SEQ_ID,locationSize=1) для увеличения только на единицу. аллокацияSize является ключом. - person dseibert; 10.12.2011
comment
Есть ли способ не использовать это? Поскольку для меня это создает огромную проблему, когда другие триггеры используют ту же последовательность для этой таблицы. Тогда они могут достичь этого числа в будущем, верно? - person Anders Metnik; 25.04.2013
comment
Посмотрите на комментарий чуть выше вашего. Используйте размер_распределения. - person JB Nizet; 27.04.2013
comment
Вау, спасибо за этот ответ. Похоже, Hibernate заново изобрел кэш последовательностей Oracle... - person Jeffrey Kemp; 01.05.2013

Я так понимаю, ваш вопрос заключается в том, что значения столбца ID в базе данных не являются естественной последовательностью, а почему вы видите пробелы:

Немного предыстории:

  • Каждый раз, когда вы вызываете select HIBERNATE_SEQUENCE.nextval from DUAL, значение последовательности увеличивается.
  • Поскольку имя вашей последовательности является общим, а не специфичным для таблицы, если у вас есть несколько объектов, которые используют HIBERNATE_SEQUENCE в качестве генератора идентификаторов, то значения из последовательностей используются во всех объектах.
  • Если какое-то другое приложение использует HIBERNATE_SEQUENCE, то это значение также пропускается.
  • Поскольку вы используете CACHE=20, Oracle будет захватывать порядковые номера блоками по 20, а затем использовать внутренний кэш для возврата чисел. Это может привести к пропуску номеров в случае потери кеша (например, при закрытии БД).
  • Если строки удаляются из вашей базы данных, значение последовательности не изменяется

Например, рассмотрим следующий сценарий:

У вас есть две сущности Entity1 и Entity2, использующие HIBERNATE_SEQUENCE в качестве генератора идентификаторов:

  1. Текущее значение HIBERNATE_SEQUENCE равно 100.
  2. Вставляется Entity1 (используется HIBERNATE_SEQUENCE, который возвращает 101)
  3. Вставляется Entity2 (используется HIBERNATE_SEQUENCE, который возвращает 102)
  4. Вставляется Entity2 (используется HIBERNATE_SEQUENCE, который возвращает 103)
  5. Объект Entity2 с идентификатором 103 удален.
  6. Вы вручную выполняете select HIBERNATE_SEQUENCE.nextval from DUAL (возвращает 104)
  7. Вставляется Entity1 (используется HIBERNATE_SEQUENCE, который возвращает 105)
  8. Вставляется Entity2 (используется HIBERNATE_SEQUENCE, который возвращает 106)

Итак, в конце у вас будет:

  • Entity1 с идентификаторами (101, 105)
  • Entity2 с идентификаторами (102, 106)

что объясняет пробелы.

РЕДАКТИРОВАТЬ:

Даже если бы @SequenceGenerator был настроен на использование SequenceGenerator, а не SequenceHiLoGenerator (как указал Дж. Б. Низе, что, я думаю, является лучшим объяснением пробелов), пробелы в идентификаторах, генерируемых последовательностями, являются обычным явлением.

person beny23    schedule 24.08.2011

person    schedule
comment
опишите свой ответ вместо копипаста - person stinger; 01.06.2018