web-dev-qa-db-ja.com

PostgreSQLシーケンスのHibernateの使用はシーケンステーブルに影響しません

次のように、(注釈を介して)PostgreSQLシーケンスを使用して主キーid列の値を生成するようにHibernateを構成しました。

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

質問:
何か問題はありませんか?
休止状態でシーケンステーブルと同期する必要がありますか?
そうでない場合、最後に生成されたIDはどこに保存されますか?

ありがとうございました。

26
forker

私も同じ問題を抱えていました。 HibernateのID割り当て戦略に関連しています。 GenerationType.SEQUENCEを選択すると、Hibernateはデフォルトで50のブロックにIDを割り当てるHiLo戦略を使用します。したがって、次のようにallocationSize値を明示的に設定できます。

@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;
}

ただし、allocationSize = 1でHiLo戦略を使用することは良い方法ではないという意見も聞いています。データベース管理のシーケンスを処理する必要がある場合は、代わりにGenerationType.AUTOの使用をお勧めします

更新:私は、allocationSize = 1を使用してしまいましたが、今のところ期待どおりに動作するようです。私のアプリケーションは、とにかく本当にIDのブロックを必要としないようなものなので、 [〜#〜] ymmv [〜#〜] です。

32
Nofate

PostgresシーケンスにはGenerationType.SEQUENCEを使用しないでください!

それは完全に直観に反しますが、Hibernateの人々はこれに完全に失敗しました。 GenerationType.AUTOを使用する必要がありますまたはDBを再起動/再構築する必要がある場合、Hibernateはシーケンスdemolishを使用します。このコードをプロダクションビルドに含めることを許可することは、ほぼ刑事的に過失ですが、Hibernateチームは、平らに間違ったポジションに向かう頭のいい姿勢で有名です(たとえば、左の結合でのポジションを確認してください)。

25
Matt Brock

まず、使用しているHibernateのバージョンを確認する必要があります。 hibernate-coreバージョンの観点から、3.2以降では、特にアノテーションでの定義に関して、IDジェネレーターに対するより一貫したサポートが導入されました。議論については http://in.relation.to/Bloggers/New323HibernateIdentifierGenerators を参照してください。

次の3.6では設定( 'hibernate.id.new_generator_mappings')が導入され、そのブログで説明されているジェネレーターがJPAアノテーションが処理されるデフォルトの方法になっています。 Hibernateは古いバージョンとの下位互換性を維持する必要があるため、この設定はデフォルトではfalseです。新しい動作が必要な場合(完全に推奨)、その設定を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クラスにマップします
8
Steve Ebersole

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;

ほとんどの場合、大文字の名前を使用します。Postgresを理解してテーブル、列、またはシーケンス名を見つけるには、Hibernateにエスケープされた引用符を渡す必要があります。

0