2012-03-25 2 views
15

У меня есть класс со следующим определением:Hibernate генерирует отрицательные значения идентификаторов при использовании последовательности

@Id 
@SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID") 
@Column(name = "ID") 
private long Id; 

Когда мы запускали его на Jboss 4.2.3 он работал отлично и генерируется собственно идентификаторы (начиная с 1000+)

Теперь мы перешли в jboss 7.1.1 и генерируем отрицательные идентификаторы! (от -498 и выше)

Любая идея, почему это может случиться?

+1

Вы проверили, что представляет собой текущая последовательность в Oracle и выводит вывод спящего режима, если вы видите правильный выбор следующего запроса последовательности, и если вы скопируете вставить в sqlplus, вы получите правильный/тот же/ожидаемый результат? – HRgiger

ответ

24

Я просто столкнулся с этой проблемой при переходе с JBoss 6.1 на JBoss 7.1.

В соответствии с JBoss AS 7.1 JPA документации (https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties),

JBoss 7.1 автоматически устанавливает несколько свойств спящего режима. Одно из заданных свойств: hibernate.id.new_generator_mappings, который активирует новые генераторы ID, которые используют разные алгоритмы и не поддерживают обратную совместимость. Установка этого свойства в false в файле persistence.xml приведет к восстановлению прежнего поведения генератора идентификаторов.

Документация о спящем режиме 4 также содержит информацию о новых генераторах идентификаторов: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator.

В документации на спящий режим четко указано, что генераторы новых идентификаторов по умолчанию не включены, но, как указано выше, JBoss 7.1 автоматически активирует их.

+0

Спасибо за ответ, я уже успел его найти, забыл обновить его здесь :( – Tomer

+0

Начиная с версии Hibernate 5.0, свойство 'hibernate.id.new_generator_mappings' по умолчанию имеет значение' true'. См. Http: //docs.jboss .org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html # идентификаторы-генераторы –

12

Установка hibernate.id.new_generator_mappings в false в моем persistence.xml была только первая часть решения моей проблемы:

Чтобы полностью решить эту проблему я добавил allocationSize к 1 в @SequenceGenerator (который я опуская).

30

Новое поведение является следующим:

AllocationSize является диапазоном значений первичного ключа, зарезервированных для Hibernate. И выбор seq.nextval из двойного будет выполняться только после того, как спящий режим потребляет этот диапазон первичных ключей.

Таким образом, вы должны объявить то же значение на обоих allocationSize (Hibernate) и последовательность increment by (DB)

При явном виде установить allocationSize=500, например, на Oracle

create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID 
     MINVALUE 1 
     MAXVALUE 999999999999999999999999999 
     START WITH 1 
     INCREMENT BY 500 
     NOCACHE 
     NOCYCLE; 

В противном случае, вы заметите отрицательные значения или ошибки ограничений, поднятых из вашей БД из первичного ключа столкновений.

Когда сервер приложений перезагружен, вы увидите «прыжок» между последним выделенным первичным ключом и «новый» порядковый номер, выбранный при перезапуске.

Окончательный комментарий: значение по умолчанию равно 50. Таким образом, если вы не укажете allocationSize на стороне Hibernate, вы должны объявить increment by 50 на стороне БД.

+0

Очень полезный ответ, поскольку эта информация, по-видимому, отсутствует в документах Hibernate. –

Смежные вопросы