Hibernateのドキュメントには次のように書かれています。
ID識別子ジェネレータを使用する場合、HibernateはJDBCレベルでの挿入のバッチ処理を透過的に無効にします。
しかし、私のすべてのエンティティはこの構成を持っています:
@Id
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
private Integer id;
上記のIDを使用している場合
IDENTITY
の何が問題なのですか?Hibernateは、可能な限り最後の瞬間まで、永続化コンテキストのフラッシュを延期しようとします。この戦略は伝統的に トランザクション後書き として知られています。
後書きは、論理的または物理的なトランザクションではなく、Hibernateフラッシュに関連しています。トランザクション中に、フラッシュが複数回発生することがあります。
フラッシュされた変更は、現在のデータベーストランザクションに対してのみ表示されます。現在のトランザクションがコミットされるまで、変更は他の同時トランザクションからは見えません。
IDENTITYジェネレーター を使用すると、必要に応じてinteger/bigint列を自動インクリメントできます。インクリメントプロセスは現在実行中のトランザクションの外部で行われるため、ロールバックによって、すでに割り当てられている値が破棄される可能性があります(値のギャップが発生する可能性があります)。
増分プロセスは、より重いトランザクションの粗粒度ロックではなく、データベースの内部軽量ロックメカニズムを使用するため、非常に効率的です。
唯一の欠点は、INSERTステートメントを実行する前に新しく割り当てられた値がわからないことです。この制限により、Hibernateで採用されている「トランザクションのライトビハインド」フラッシュ戦略が妨げられています。このため、HibernateはIDENTITYジェネレーターを使用するエンティティのJDBCバッチサポートを無効にします。
唯一の解決策は、 pooled-loオプティマイザ に裏打ちされたTABLE識別子ジェネレータを使用することです。このジェネレーターはMySQLでも動作するため、データベースのシーケンスサポートの欠如を克服します。ただし、 TABLEジェネレーターはIDENTITYよりもパフォーマンスが悪い なので、結局、これは実行可能な代替策ではありません。したがって、MySQLではIDENTITYを使用することが依然として最良の選択です。挿入にバッチ処理が必要な場合は、 そのためにjOOQを使用できます です。 HibernateとjOOQは素晴らしいコンボです。