次の定義を持つクラスがあります。
@Id
@SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID")
@Column(name = "ID")
private long Id;
Jboss 4.2.3で実行すると、正常に機能し、適切なIDが生成されました(1000以上から開始)
ここでjboss 7.1.1に移動すると、負のIDが生成されます! (-498から開始して上昇)
なぜこれが起こる可能性がありますか?
JBoss 6.1からJBoss 7.1に移行するときにこの問題に遭遇しました。
JBoss AS 7.1 JPAドキュメント( https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties )によると、
JBoss 7.1はいくつかのhibernateプロパティを自動的に設定します。設定されているプロパティの1つはhibernate.id.new_generator_mappings
異なるアルゴリズムを使用し、下位互換性のない新しいIDジェネレーターをアクティブにします。 persistence.xmlファイルでこのプロパティをfalseに設定すると、古いIDジェネレーターの動作が復元されます。
Hibernate 4のドキュメントには、新しいIDジェネレーターに関する情報も含まれています。 http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator 。
Hibernateのドキュメントには、新しいIDジェネレーターがデフォルトで有効になっていないことが明確に記載されていますが、上記のように、JBoss 7.1は自動的に有効にします。
新しい動作は次のとおりです。
AllocationSizeは、Hibernate用に予約されている主キー値の範囲です。また、デュアルからのseq.nextval
の選択は、休止状態がこの範囲の主キーを消費した後にのみ行われます。
したがって、mustallocationSize
(Hibernate)とシーケンスincrement by
(DB)の両方で同じ値を宣言します
allocationSize=500
を明示的に設定する場合、例: Oracleで
create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID
MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 500
NOCACHE
NOCYCLE;
そうしないと、主キーの衝突のために、DBから負の値または制約エラーが発生します。
アプリサーバーを再起動すると、割り当てられた最新のプライマリキーと再起動時に選択された「新たな」シーケンス番号の間の「ジャンプ」に気付くでしょう。
最終コメント:デフォルト値は50です。したがって、Hibernate側でallocationSize
を指定しない場合、DB側でmustを宣言するincrement by
50です。
hibernate.id.new_generator_mappings
でpersistence.xml
をfalse
に設定することは、私の問題に対する解決策の最初の部分にすぎません。
問題を完全に解決するために、1
の@SequenceGenerator
にallocationSize
を追加しました(これは省略していました)。