138

使用時の Hibernate のデフォルトの動作は周知のとおりです。@SequenceGenerator実際のデータベース シーケンスを1増やし、この値を 50 倍して (デフォルトallocationSize値)、この値をエンティティ ID として使用します。

これは正しくない動作であり、次の仕様と矛盾します。

allocationSize - (オプション) シーケンスからシーケンス番号を割り当てるときに増分する量。

明確にするために: 生成された ID 間のギャップについては気にしません。

基礎となるデータベース シーケンスと一致しないID が気になります。例: 他のアプリケーション (プレーンな JDBC を使用するアプリケーションなど) は、シーケンスから取得した ID の下に新しい行を挿入したい場合がありますが、それらの値はすべて Hibernate によって既に使用されている可能性があります! 狂気。

誰かがこの問題の解決策を知っていますか (設定せずにallocationSize=1パフォーマンスを低下させません)?

編集:
物事を明確にするために。最後に挿入されたレコードに ID = があった場合1、HB は51, 52, 53...新しいエンティティの値を使用しますが、同時に、データベース内のシーケンスの値は に設定され2ます。他のアプリケーションがそのシーケンスを使用している場合、これは簡単にエラーにつながる可能性があります。

一方:仕様では、(私の理解では)データベースシーケンスをに設定する必要が51あり、その間、HBは範囲の値を使用する必要 があると述べています2, 3 ... 50


更新:
Steve Ebersole が以下に述べたように: 私が説明した動作 (および多くの人にとって最も直感的な動作) は、設定することで有効にできますhibernate.id.new_generator_mappings=true

皆さんに感謝します。

更新 2:
将来の読者のために、以下に実際の例を示します。

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
    @SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
    private Long id;
}

persistence.xml

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>
4

6 に答える 6

55

明確にするために...あなたが説明することは、仕様とはまったく矛盾しません。この仕様では、データベース シーケンスに実際に格納されている値ではなく、Hibernate がエンティティに割り当てる値について説明しています。

ただし、探している動作を取得するオプションがあります。まず、JPA アノテーションと Hibernate を使用して @GeneratedValue 戦略を動的に選択する方法はありますか?に関する私の返信を参照してください。 それはあなたに基本を与えるでしょう。その SequenceStyleGenerator を使用するように設定されている限り、Hibernate は SequenceStyleGeneratorallocationSizeの「プールされたオプティマイザー」を使用して解釈します。「プールされたオプティマイザー」は、シーケンスの作成時に「インクリメント」オプションを許可するデータベースで使用するためのものです (シーケンスをサポートするすべてのデータベースがインクリメントをサポートしているわけではありません)。とにかく、そこにあるさまざまなオプティマイザー戦略について読んでください。

于 2012-10-05T13:35:31.900 に答える
24

allocationSize=1これは、クエリを取得する前のマイクロ最適化です。HibernateはallocationSizeの範囲で値を割り当てようとするため、データベースにシーケンスをクエリしないようにしてください。ただし、このクエリは1に設定すると毎回実行されます。これは、データベースが他のアプリケーションによってアクセスされている場合、同じIDが別のアプリケーションによって使用されていると問題が発生するため、ほとんど違いはありません。

次世代のシーケンスIDはallocationSizeに基づいています。

defualtによって、50それは多すぎるように保たれます。50また、永続化されておらず、この特定のセッションとトランザクションを使用して永続化される1つのセッションのレコードがほぼある場合にのみ役立ちます。

したがって、を使用しているallocationSize=1間は常に使用する必要がありますSequenceGenerator。基盤となるデータベースのほとんどについては、シーケンスは常に。でインクリメントされ1ます。

于 2012-10-05T12:04:09.050 に答える
2

スキーマ内のシーケンスの DDL を確認します。JPA 実装は、正しい割り当てサイズでのシーケンスの作成のみを担当します。したがって、割り当てサイズが 50 の場合、シーケンスの DDL には 50 のインクリメントが必要です。

このケースは通常、割り当てサイズ 1 でシーケンスを作成し、後で割り当てサイズ 50 (またはデフォルト) に構成した場合に発生する可能性がありますが、シーケンス DDL は更新されません。

于 2012-10-05T19:13:42.947 に答える