22

オラクルシーケンスを使用するように休止状態を構成しました。シーケンスは cache=20、increment=1 で作成されます。

すべて正常に動作し、エンティティを休止状態にします。ID 値がおかしい: 50,51....76,201,202...209,1008,1009,5129,5130 ....

シーケンス値を要求すると (デュアルから hibernate_sequence.nextval を選択)、2,3,4 のような値が得られます ....

ハイバネート SQL デバッグをオンにすると、「デュアルから hibernate_sequence.nextval を選択」という呼び出しが時々ありますが、ハイバネートによって ID に割り当てられた番号がシーケンスでリレーされません!

@Id
@Column(name = "ID", insertable = false, updatable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private Long id;
4

3 に答える 3

34

これは、SequenceGenerator が実際にはシーケンス ジェネレーターではないためです。シーケンス ハイロー ジェネレーターです。これは、最初に呼び出されたときに、シーケンスから次の値 (たとえば 6) を取得し、この値を 50 倍して結果 (300) を返すことを意味します。次回呼び出されると、301 が返され (シーケンスに移動せずに)、349 に達するまで繰り返されます。次に、シーケンスに次の値を要求し、7 を取得します。これに再び 50 を掛けて 350 を返します。アルゴリズムの説明は 1 つずれている可能性がありますが、おわかりいただけたでしょうか。

アプリケーションを停止して開始すると、ギャップが生じます。ただし、50 世代に 1 回しかデータベース呼び出しを行わないため、純粋なシーケンス ジェネレーターよりも効率的です。

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizersおよびhttp://docs.jboss.org/hibernate/core/を参照してください。詳細については、 3.6/reference/en-US/html_single/#mapping-declaration-id-generatorを参照してください。

于 2011-08-24T07:22:21.833 に答える
8

あなたの質問は、データベースの ID 列の値が自然なシーケンスではなく、なぜギャップが見られるのかということだと思います。

背景のビット:

  • 呼び出すたびselect HIBERNATE_SEQUENCE.nextval from DUALに、シーケンスの値が増加します。
  • シーケンス名はテーブルに固有のものではなく一般的なものであるため、ID ジェネレーターとして HIBERNATE_SEQUENCE をすべて使用する複数のエンティティがある場合、シーケンスの値がすべてのエンティティで使用されます。
  • 他のアプリケーションが HIBERNATE_SEQUENCE を使用している場合、値もスキップされます。
  • CACHE=20 を使用しているため、Oracle は 20 のブロックでシーケンス番号を取得し、内部キャッシュを使用して番号を返します。これにより、キャッシュが失われた場合 (DB がシャットダウンされた場合など)、番号がスキップされる可能性があります。
  • データベースから行が削除されても、シーケンス値は変更されません

たとえば、次のシナリオを考えてみましょう。

ID ジェネレーターとして HIBERNATE_SEQUENCE を使用する 2 つのエンティティ Entity1 と Entity2 があります。

  1. 現在の HIBERNATE_SEQUENCE 値は 100 です
  2. Entity1 が挿入されます (101 を返す HIBERNATE_SEQUENCE を使用)
  3. Entity2 が挿入されます (102 を返す HIBERNATE_SEQUENCE を使用)
  4. Entity2 が挿入されます (103 を返す HIBERNATE_SEQUENCE を使用)
  5. ID 103 の Entity2 が削除されます
  6. 手動で実行しselect HIBERNATE_SEQUENCE.nextval from DUALます (104 を返します)
  7. Entity1 が挿入されます (105 を返す HIBERNATE_SEQUENCE を使用)
  8. Entity2 が挿入されます (106 を返す HIBERNATE_SEQUENCE を使用)

したがって、最後には次のようになります。

  • ID を持つ Entity1 (101、105)
  • ID を持つ Entity2 (102、106)

ギャップを説明します。

編集:

@SequenceGenerator がSequenceGeneratorではなくを使用するように設定SequenceHiLoGeneratorされていたとしても (JB Nizet が指摘したように、ギャップのより良い説明だと思います)、シーケンスによって生成された ID のギャップはよくあることです。

于 2011-08-24T07:22:42.047 に答える
-2
CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1;
grant all on SEQ_SEQUENCENAME to public;

@Id
@Column(name = "ID", unique = true, nullable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private int Id;
于 2016-07-28T04:14:03.353 に答える