8

純粋な JPA アノテーションを使用して、いくつかの Hibernate エンティティを定義しました。これらは、データベースで事前定義された Oracle シーケンスを使用して、主キー値を自動的に生成します。

@Id
@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_ID_GENERATOR")
@Column(name = "U_ID", updatable = false, unique = true, nullable = false, precision = 19)
private Long id;

これを JBoss EAP 6.1 にデプロイすると、最初はすべて正常に動作しますが、しばらくすると Hibernate が挿入時に重複キーを生成し始めます (ORA-00001 エラー)。

ID の順序やギャップは気にしませんが、キーの重複は許容できません... ここで何が起こっているのでしょうか?

4

2 に答える 2

14

これは十分に文書化されていません。ここや他のサイトのソリューションの多くは、HiLo sequenceGenerator がデフォルトであった古いバージョンの hibernate に関連しています。しかし、調査の結果、根本的な原因は JBoss EAP 6 セット

hibernate.id.new_generator_mappings=true 

デフォルトでは、古いバージョンの代わりに org.org.hibernate.id.enhanced.SequenceStyleGenerator を使用します。

Hibernate SequenceStyleGenerator のデフォルトのインクリメントは 1 (コードを確認してください!) ですが、JPA はこのジェネレーターのインクリメント値を 50 にオーバーライドします。これは、ジェネレーターがシーケンス nextval を調べ、使用する 50 個の ID のキャッシュを保持することを意味します。 49. これらが使い果たされると、ジェネレーターはオラクルから次のシーケンスを読み取り、プロセスを繰り返します。そのため、最初の一連の ID が使い果たされると、重複したキーが表示され始めます。

したがって、解決策は次のとおりです。

1) Oracle シーケンスを増分値 50 で定義して、JPA のデフォルトと一致させます。

CREATE SEQUENCE MY_SEQ
START WITH 50
MAXVALUE 9999999999999999999
INCREMENT BY 50
NOCYCLE;

また

2) allocationSize=1 を @SequenceGenerator アノテーションに追加します。これにより、SequenceGenerator は、必要な ID ごとに Oracle シーケンスから次の値を読み取るように強制されます (パフォーマンスに影響を与える可能性があります)。

 @SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ", allocationSize = 1)

、 また

3) Oracle シーケンス INCREMENT BY を他の値で定義し、allocationSize が一致するようにします。

この問題を抱えている他の人を助けることを期待して、私自身の質問に答えました。

于 2013-07-24T05:17:49.020 に答える
1

あなたの答えは正しいです。もう少し詳細です。

一部の投稿では、hibernate.id.new_generator_mappings=false をオフにすることを提案しています。

しかし、 https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitpropertiesによると

GenerationType.AUTO と GenerationType.SEQUENCE には違いがあります

AUTO を選択すると、休止状態のネイティブが選択されます。SEQUENCE を選択すると、シーケンスの割り当てに hilo アルゴリズムが一致しますが、これは SequenceStyleGenerator とはまったく異なります。hibernate.id.new_generator_mappings=true / false を切り替えると互換性がなくなります。

したがって、答え1)は間違いなく正しいものです/現在のHibernate / Jbossの推奨事項に従っています。

...そして、すべてのエンティティにallocationSize=1を設定する答えは良い解決策ではありません。http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/を参照してください 。

于 2013-09-26T20:21:44.070 に答える