web-dev-qa-db-ja.com

休止状態は次のシーケンス値を取得できませんでした

バックエンドでgwtアプリケーションをpostgres DBに接続し、DBのテーブル 'judgements'をマッピングするJava class 'Judgement'、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

私の判断クラスは次のようになります

@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)

そして、私はDBにシーケンス名「judgements_id_seq」を持っています

誰が間違っているのか教えてもらえますか???ありがとう。

42
user468587

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が既存のキーを再利用しようとするため、一意の違反が発生します。

一度に1つのキーを取得すると、挿入ごとに追加のラウンドトリップが発生することに注意してください。私が知る限り、HibernateはINSERT ... RETURNINGを使用して生成されたキーを効率的に返すことができず、JDBCによって生成されたキーインターフェイスを使用することもできません。シーケンスを使用するように指示すると、nextvalを呼び出して値を取得し、その後明示的にinsertを呼び出して、2回のラウンドトリップを行います。そのコストを削減するために、マッピングおよび基になるデータベースシーケンスに設定することを忘れずに、挿入が多いキーシーケンスに大きな増分を設定できます。これにより、Hibernateはnextvalをあまり頻繁に呼び出さずに、キーのブロックをキャッシュして、そのまま配布します。

上記から、少なくともPostgreSQLで使用するという観点から、ここで行ったHibernateの設計選択に同意しないことがわかると思います。 getGeneratedKeysを使用するか、キーにDEFAULTとともにINSERT ... RETURNINGを使用する必要があります。これにより、データベースはHibernateがシーケンスの名前や明示的なアクセスをめぐって問題なく処理できます。

ところで、PgでHibernateを使用している場合は、おそらく Pgのoplockトリガー を使用して、Hibernateの楽観的ロックが通常のデータベースロックと安全に対話できるようにすることもできます。 Hibernateの更新は、他の通常のSQLクライアントを介して行われた変更を上書きする傾向があります。どうやって知っているか聞いてください。

81
Craig Ringer

PostgreSQLでHibernateが 'serial'列を使用するようにするには、@GeneratedValue(strategy = GenerationType.IDENTITY)を使用しなければならなかったことを思い出すようです。

42
davidg

GenerationType.AUTOの代わりに戦略GenerationType.IDENTITYを使用して@GeneratedId列を設定する必要があります。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "JUD_ID")
private Long _judId;
12
virag

以前にも同じエラーが発生しました。データベースにこのクエリを入力してくださいCREATE SEQUENCE hibernate_sequence START WITH 1 INCREMENT BY 1 NOCYCLE;

それは私のために働いています、幸運〜

9
splatter_fadli

また、MySQLからPostgreSQLへの移行に関するいくつかのメモを追加したいと思います。

  1. DDLでは、オブジェクトの命名では、キャメルケースの規則よりも、単語の区切りに「_」(アンダースコア)文字を使用することをお勧めします。後者はMySQLで正常に動作しますが、PostgreSQLで多くの問題をもたらします。
  2. モデルのクラスIDフィールドの@GeneratedValueアノテーションのIDENTITY戦略は、Hibernate 3.2以降のPostgreSQLDialectで正常に機能します。また、AUTO戦略はMySQLDialectの典型的な設定です。
  3. @Tableでモデルクラスに注釈を付け、これらにリテラル値をテーブル名と同じ値に設定する場合、パブリックスキーマの下に格納されるテーブルを作成したことを確認してください。

私が今覚えている限りでは、これらのヒントが試行錯誤の数分をあなたの手間を省くことを願っています!

2
RickB

あなたはすでに十分な答えを持っていると思いますが、私はまったく同じエラーを受け取り、私の問題は別のものでした。そして、それを解決しようとして少し時間を無駄にしました。

私の場合、問題は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;

誰にとっても役立つことを願っています。

2

GeneratedValueおよびGenericGeneratornative戦略とともに使用する:

@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はデフォルトでそのようなシーケンスを検索するため、シーケンス呼び出しhibernate_sequenceを作成する必要がありました。

create sequence hibernate_sequence start with 1 increment by 50;
grant usage, select on all sequences in schema public to my_user_name;
1
Stephane

Postgresを使用している場合、「hibernate_sequence」という名前のシーケンスを手動で作成します。それが動作します。

0
Rajdeep

使用しているデータベースは、Postgres SQL設定ファイルのsearch_pathに記載する必要があります。これは、たとえばTESTDBなどのデータベース名とともにsearch_pathを設定して、Postgressql構成ファイルを編集することで実行できます。

  1. Postgres SQL datbaseのdataフォルダーの下にあるpostgressql.confファイルを見つけます。
  2. Search_path = "$ user"、public、TESTDBを設定します。
  3. Postgres SQLサービスを再起動して、変更を有効にします。

上記の変更を行った後、私にとってはうまくいきました。

0
Chaitanya Ankam