Спящий режим использования последовательности PostgreSQL не влияет на таблицу последовательности - PullRequest
26 голосов
/ 27 ноября 2010

Я настроил Hibernate для использования последовательности PostgreSQL (с помощью аннотаций) для генерации значений для первичного ключа id столбца следующим образом:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
@Column(name="id", unique=true, nullable=false)
public int getId() {
    return this.id;
}

В этой конфигурации я вижу, что hibernate уже присваивает id значения> 3000 при сохранении, тогда как запрос на использованную последовательность показывает следующее:

database=# select last_value from entity_id_seq;
last_value 
------------
     69

(1 строка)

Вопросы:
Что-то не так или нет?
Должен ли спящий режим синхронизироваться с таблицей последовательности?
Если нет, где хранится последний сгенерированный идентификатор?

Спасибо.

Ответы [ 4 ]

31 голосов
/ 27 ноября 2010

У меня была такая же проблема. Это связано со стратегиями распределения идентификаторов Hibernate. Когда вы выбираете GenerationType.SEQUENCE , Hibernate использует стратегию HiLo, которая по умолчанию распределяет идентификаторы в блоках по 50. Таким образом, вы можете явно установить allocSize значение следующим образом:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
@Column(name="id", unique=true, nullable=false)
public int getId() {
    return this.id;
}

Хотя я также слышал мнения, что использование стратегии HiLo с allocSize = 1 не является хорошей практикой. Некоторые люди рекомендуют использовать GenerationType.AUTO вместо того, чтобы иметь дело с последовательностями, управляемыми базой данных

Обновление: Я все-таки остановился на allocSize = 1, и теперь все работает так, как я ожидаю. Мое приложение таково, что мне все равно не нужны блоки идентификаторов, поэтому YMMV .

23 голосов
/ 21 декабря 2010

НЕ ИСПОЛЬЗУЙТЕ GenerationType.SEQUENCE для последовательностей Postgres!

Это абсолютно нелогично, но ребята из Hibernate полностью запутались в этом.Вы должны использовать GenerationType.AUTO или Hibernate уничтожит ваших последовательностей, если вам придется перезапускать / восстанавливать вашу БД.Почти преступно небрежно, что они позволят этому коду войти в производственную сборку, но команда Hibernate довольно известна своими тупыми позициями по отношению к категорически неправильным позициям (см., Например, их позицию на LEFT JOINs).

8 голосов
/ 06 декабря 2011

Сначала вы должны определить, какую версию Hibernate вы используете. Что касается версий hibernate-core, в версии 3.2 и выше появилась более согласованная поддержка генераторов идентификаторов, особенно в отношении определенных в аннотациях. См. http://in.relation.to/Bloggers/New323HibernateIdentifierGenerators для обсуждения.

Следующие 3.6 представили настройку ('hibernate.id.new_generator_mappings'), которая делает генераторы, обсуждаемые в этом блоге, способом обработки JPA-аннотаций по умолчанию. Значение по умолчанию равно false, поскольку Hibernate должен поддерживать обратную совместимость со старыми версиями. Если вы хотите новое поведение (что полностью рекомендуется), просто установите для этого параметра значение true.

То, как обрабатывается GenerationType, зависит от того, какую версию вы используете, и для параметра hibernate.id.new_generator_mappings установлено значение true. Я предполагаю, что вы используете 3.6+ (поскольку все старое, ну, в общем, старое) и для 'hibernate.id.new_generator_mappings' установлено значение true (поскольку это рекомендация для новых приложений):

  1. GenerationType.AUTO -> обрабатывается как GenerationType.SEQUENCE
  2. GenerationType.SEQUENCE -> соответствует классу org.hibernate.id.enhanced.SequenceStyleGenerator, обсуждаемому в блоге
  3. GenerationType.TABLE -> соответствует классу org.hibernate.id.enhanced.TableGenerator, обсуждаемому в блоге
0 голосов
/ 03 октября 2012

В Postgres я бы сделал это:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="\"entity_id_seq\"")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="\"pk_sequence\"")
@Column(name="\"id\"", unique=true)
private int id;

В основном с именами в верхнем регистре Hibernate необходимо передавать через кавычки, чтобы понять Postgres и найти имена таблиц, столбцов или последовательностей.

...