Подтвердить что ты не робот

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;
4b9b3361

Ответ 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;