Hibernate 6 でデフォルトのプライマリキー採番方法が変更になって、hibernate_sequence からではなく、テーブル名_seq から採番するようになった。これまでの採番方式を維持するためには、persistent.xml に以下のように記載しなくてはならない。
<property name="hibernate.id.db_structure_naming_strategy" value="single" />
今回、これに気付かずに運用開始してやらかしてしまった。Hibernate 5 の時はテスト段階で警告が出てくれたので、hibernate.model.generator_name_as_sequence_name=false をセットして事なきを得たが、今回は警告も出ないし、テストでエラーも出なかったので、完全に油断していた。
木曜日から運用開始して、金曜日まで問題なし。そして土曜日、診療開始してしばらくしてからエラーが出るようになった。
2023-01-28 09:04:22,093 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-80) SQL Error: 0, SQLState: 23505
2023-01-28 09:04:22,093 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-80) ERROR: duplicate key value violates unique constraint "d_module_pkey"
詳細: Key (id)=(1070) already exists.
土曜日は患者さん多く、すぐに対応するのは不可能。全身から血の気が引いたが、何回か再送すると動くので、頑張って運用を続けた。再送2−3回で送らさったのが多かったが、最高10回再送でやっと通ったのもあった。そして、幸運にも何とか外来終了することができて、最後のカルテが保存できた時は、本当にほっとして力が抜けた。
トラブルの原因となったプライマリーキーの件は、土曜外来終了後に web 検索して判明した。多分、プライマリーキーの若い番号は ModuleModel には割当たってなかったので、最初の1000番くらいは空きがあったのだろう。それを食い尽くして、何とか隙間にねじ込むしかなくなったのが土曜日だったのだと思われる。次回はちゃんとマイグレーションマニュアル読もうと誓った週末であった。
ちなみに、Hibernate 6 の新しいデフォルトの採番は、テーブルごとにインクリメントしていくので、効率的に採番できてよい方法だと思う。当院のように hibernate_sequence を single で使ってしまっていると、bigint なので最大 9,223,372,036,854,775,807 までしか使えない。当院の hibernate_sequence は 15年で既に 2,725,392 に達しており、このままのペースで行くと 50,763,552,748,661年後には使い果たしてしまうことになる。