Hibernate не может получить следующее значение последовательности
У меня есть приложение gwt подключиться к DB постгерса на бэкэнд, а java-класс "Суждение", отображающее "суждения" таблицы в БД, когда я пытался настойчиво судить в db, он выдавал следующие ошибки:
Caused by: org.hibernate.exception.SQLGrammarException: could not get next sequence value
...
Caused by: org.postgresql.util.PSQLException: ERROR: relation "hibernate_sequence" does not exist
мой класс Judgment выглядит следующим образом
@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {
private static final long serialVersionUID = -7049957706738879274L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "JUD_ID")
private Long _judId;
...
и мои суждения в таблице:
Column | Type | Modifiers
-------------+-----------------------------+---------------------------------------------------------
jud_id | bigint | not null default nextval('judgements_id_seq'::regclass)
rating | character varying(255) |
last_update | timestamp without time zone |
user_id | character varying(255) |
id | integer |
Indexes:
"judgements_pkey" PRIMARY KEY, btree (jud_id)
Foreign-key constraints:
"judgements_id_fkey" FOREIGN KEY (id) REFERENCES recommendations(id)
"judgements_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(user_id)
и у меня есть имя SEQUENCE 'judments_id_seq' в DB
может кто-нибудь сказать мне, что случилось??? спасибо.
Ответы
Ответ 1
Диалог Hibernate PostgreSQL не очень яркий. Он не знает о ваших последовательностях в SERIAL и предполагает наличие глобальной последовательности в базе данных, называемой "hibernate_sequence", которую он может использовать.
(UPDATE). Похоже, что более новые версии Hibernate могут использовать последовательности по умолчанию для каждой таблицы, если указан GenerationType.IDENTITY
. Проверьте свою версию и используйте ее вместо ниже, если она работает для вас. )
Вам нужно изменить свои сопоставления, чтобы явно указать каждую последовательность. Это раздражает, повторяется и бессмысленно.
@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {
private static final long serialVersionUID = -7049957706738879274L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
@SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
@Column(name = "JUD_ID")
private Long _judId;
...
allocationSize=1
очень важен. Если вы опустите его, Hibernate будет вслепую предположить, что последовательность определяется с помощью INCREMENT 50
, поэтому, когда она получает значение из последовательности, она может использовать это значение и 49 значений под ним как уникальные сгенерированные ключи. Если ваши последовательности базы данных увеличиваются на 1 - по умолчанию - тогда это приведет к уникальным нарушениям, так как Hibernate пытается повторно использовать существующие ключи.
Обратите внимание, что получение одного ключа за раз приведет к дополнительному кругообороту на каждую вставку. Насколько я могу судить, Hibernate не способен использовать INSERT ... RETURNING
для эффективного возврата сгенерированных ключей и, по-видимому, не может использовать интерфейс сгенерированных ключей JDBC. Если вы скажете ему использовать последовательность, он вызовет nextval
, чтобы получить значение then insert
, которое явно, что приведет к двум раундам. Чтобы снизить затраты на это, вы можете установить большее увеличение на последовательности клавиш с большим количеством вставок, не забывая установить его на карте и базовой последовательности базы данных. Это приведет к тому, что Hibernate вызовет nextval
реже и блокирует кеш-ключи для раздачи по мере их появления.
Я уверен, что вы можете видеть из вышеизложенного, что я не согласен с выбором дизайна Hibernate, сделанным здесь, по крайней мере, с точки зрения использования его с PostgreSQL. Они должны использовать getGeneratedKeys
или использовать INSERT ... RETURNING
с DEFAULT
для ключа, позволяя базе данных позаботиться об этом без спящего режима, чтобы беспокоиться о именах последовательностей или явного доступа к ним.
Кстати, если вы используете Hibernate с Pg, вам также понадобится триггер oplock для Pg, чтобы позволить оптимистичной блокировке Hibernate безопасно взаимодействовать с нормальной блокировкой базы данных, Без него или что-то вроде этого ваши обновления Hibernate будут иметь тенденцию к изменениям clobber, сделанным с помощью других обычных SQL-клиентов. Спросите меня, как я знаю.
Ответ 2
Кажется, мне кажется, что нужно использовать @GeneratedValue(strategy = GenerationType.IDENTITY)
, чтобы заставить Hibernate использовать столбцы "serial" на PostgreSQL.
Ответ 3
Вам нужно установить столбец @GeneratedId со стратегией GenerationType.IDENTITY вместо GenerationType.AUTO
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "JUD_ID")
private Long _judId;
Ответ 4
Я получил такую же ошибку раньше,
введите этот запрос в свою базу данных CREATE SEQUENCE hibernate_sequence START WITH 1 INCREMENT BY 1 NOCYCLE;
которые работают для меня, удачи ~
Ответ 5
Я также хотел бы добавить несколько заметок о миграции MySQL-to-PostgreSQL:
- В вашем DDL, в названии объекта предпочтительнее использовать символ "_" (подчеркивание) для разделения слов на случай верблюда. Последнее отлично работает в MySQL, но приносит много проблем в PostgreSQL.
- Стратегия IDENTITY для аннотации @GeneratedValue в ваших полях идентичности класса модели отлично работает для PostgreSQLDialect в спящем режиме 3.2 и выше. Кроме того, стратегия AUTO является типичной настройкой для MySQLDialect.
- Если вы комментируете свои классы моделей с помощью @Table и задаете буквальное значение, равное имени таблицы, убедитесь, что вы создали таблицы, которые будут храниться в общедоступной схеме.
Что, насколько я помню сейчас, надеюсь, что эти советы помогут вам немного минут проб и ошибок!
Ответ 6
Я думаю, что у вас уже есть достаточно ответа, но я получил точно такую же ошибку, и моя проблема была другой. И я потратил немного времени на ее решение.
В моем случае проблема была владельцем последовательности в Postgres. Итак, если какое-либо решение выше не решило вашу проблему, проверьте, является ли владелец последовательности пользователем/ролью, которая должна иметь разрешение.
Выполняет выборку:
CREATE SEQUENCE seq_abcd
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.seq_abcd OWNER TO USER_APP;
Я надеюсь, что это может быть полезно для всех.
Ответ 7
Использование GeneratedValue
и GenericGenerator
с native
стратегией:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_native")
@GenericGenerator(name = "id_native", strategy = "native")
@Column(name = "id", updatable = false, nullable = false)
private Long id;
Мне пришлось создать вызов последовательности hibernate_sequence
поскольку Hibernate по умолчанию ищет такую последовательность:
create sequence hibernate_sequence start with 1 increment by 50;
grant usage, select on all sequences in schema public to my_user_name;
Ответ 8
База данных, которую мы используем, должна быть указана в поле search_path в файле конфигурации Postgres SQL. Это можно сделать, отредактировав файл конфигурации Postgressql, установив search_path вместе с именем базы данных, например: TESTDB.
- Найдите файл postgressql.conf в папке данных базы данных SQL Postgres.
- Set search_path = "$ user", public, TESTDB;
- Перезапустите службу Postgres SQL, чтобы изменения вступили в силу.
Это сработало для меня после внесения вышеуказанных изменений.
Ответ 9
При использовании Postgres создайте последовательность вручную с именем "hibernate_sequence". Это будет работать.
Ответ 10
Пожалуйста, используйте следующий запрос и измените вашу таблицу: CREATE SEQUENCE user_id_seq START 1;
ALTER TABLE product.users ALTER COLUMN user_id SET DEFAULT nextval('user_id_seq');
ALTER SEQUENCE users.user_id_seq OWNED BY users.user_id;
и используйте this в своем классе сущностей
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="user_id_seq")