データモデルのリファクタリング後にデータ移行を行っており、複合主キーを持ついくつかのテーブルを取得し、それらをより大きなテーブルに結合して、独自の一意の主キーを与えています。この時点で、古いテーブル データを新しいテーブルにコピーし、AUTO_INCREMENT を使用して主キーを割り当てる SQL を記述しました。移行が完了したら、PK フィールドから AUTO_INCREMENT を削除します。これで問題は解決しましたが、問題は、次に利用可能な PK が何であるかを知るために休止状態シーケンスが必要なことです。私たちは通常、すべてのエンティティに TABLE 戦略を使用していますが、一貫性を保ち、将来のオブジェクトに AUTO_INCREMENT と IDENTITY 戦略を使用しないようにしたいと考えています。生成された「hibernate_sequences」でそれぞれの行を一時的に設定することで逃げました table を新しく作成されたテーブルの最大 ID に変更しますが、これは問題に対する一時的な修正にすぎません。また、これにより、次に作成される ID が最大 ID よりもはるかに大きくなります。これは、HiLo の ID 割り当てメカニズムを理解していないためだと確信しています。そのため、ここに投稿しています。Idが連続するようにこれを設定する方法はありますか? または、HiLo 値を生成して連続した ID を確保するために必要な値を計算できるコードはどこにありますか?
2 に答える
私があなたを正しく理解していれば、問題は hibernate が連続した ID を生成しないことです。しかし、それがハイ/ロージェネレーターの仕組みであり、なぜあなたが気に入らないのか正確にはわかりません.
基本的に、Hi/lo ジェネレーターは、HIGH 値と LOW 値を別々にサポートすることに基づいています。LOW が限界に達するとリセットされ、HIGH がインクリメントされます。結果キーは、HIGH 値と LOW 値の組み合わせに基づいています。たとえば、キーがダブルワードで、HIGH と LOW が単語であるとします。HIGH は左に 2 バイト、LOW は右に 2 バイトです。
ID のジャンプは、LOW の最大値と、HIGH の値の変更をトリガーするイベントの 2 つの要因に依存します。Hibernate のデフォルトでは、LOW の最大値は Short.MAX_VALUE であり、ジェネレーターの初期化ごとにリセットされます。HIGH 値はテーブルから読み取られ、初期化のたびにインクリメントされます。また、LOW が上限に達するとインクリメントされます。これはすべて、アプリケーションを再起動するたびに、ID にギャップが生じることを意味します。
コードを見ると、max_lo に値 <1 を使用すると、DB から読み取られる hi 値をインクリメントするだけでキーが生成されるようです。あなたはおそらくその振る舞いを好むでしょう:)
org.hibernate.id.MultipleHiLoPerTableGenerator#generate のソース コードを見てください。
を使用org.hibernate.id.MultipleHiLoPerTableGenerator#generate
すると、バッチのサイズが 50 であることがわかりました。そのため、最大 ID / 50 + 1 を使用する目的のために、使用可能な数値を生成してシーケンスに投入し、それらを可能な限りシーケンシャルに近づけました。