31

次のように、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が永続化時にすでに3000を超えるID値を割り当てているのに対し、使用されているシーケンスのクエリは次のことを示しています。

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

(1行)

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

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

4

4 に答える 4

42

私も同じ問題を抱えていました。これは、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です。

于 2010-11-26T22:27:28.470 に答える
31

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

それは完全に直感に反しますが、休止状態の人々はこれを完全に台無しにしました。DBを再起動/再構築する必要がある場合は、GenerationType.AUTOを使用する必要があります。そうしないと、Hibernateによってシーケンスが破棄されます。このコードを本番ビルドに入れることを許可することはほとんど過失犯ですが、Hibernateチームは、フラットに間違った位置に対する彼らの強気な姿勢でかなり有名です(たとえば、LEFT JOINでの位置を確認してください)。

于 2010-12-21T17:21:33.043 に答える
9

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

次の3.6では、そのブログで説明されているジェネレーターをJPAアノテーションのデフォルトの処理方法にする設定('hibernate.id.new_generator_mappings')が導入されました。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クラスにマップします
于 2011-12-05T20:36:06.333 に答える
0

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にエスケープされた引用符を渡す必要があります。

于 2012-10-03T15:43:09.647 に答える