概要
JPAでの楽観ロックの実装をしたが、JPAの理解度が低いところから、思わぬところで排他制御が動いてしまうという事象が多発した。
はまった実装方法の備忘録として記録しておく。
楽観ロックの仕組み
基本的な楽観ロックのかけ方は下記記事と同様である。
1. テーブルにVesionカラムを追加
2. エンティティクラスに@Versionアノテーションを付与する。
ただこの楽観制御だけでは、
排他がかかってほしいタイミングで排他がかからなかった。
After:画面表示時にエンティティを取得しバージョンを保持して、更新時にバージョンの現新比較を行い、排他制御をかけた
(図説がやっつけで申し訳ない)
現新比較では下記の実装で実現させている
- EntityBaseの継承
・EntityBaseはOldVersionを持つ(画面表示時の格納用項目)
・@PreUpdateをつけたメソッドでOldVersionとVersionの比較を行う。(更新前自動呼出し)
はまったこと
ここからが本題です。
①更新対象EntityをFindByメソッドで取得するタイミングはsaveの直前とする
取得~saveまでの間に別のrepositoryのfindByを動かすと、versionが意図せずインクリメントされ、不適切な楽観ロックエラーが発生することがある
②排他制御のため特定のテーブルのバージョンのみを更新したい場合、明示的に更新日付などをセットして更新する必要がある
変更された項目がないとupdateが実行されないため
③DBから取得したEntitynに対してはVersionは上書きできない
JPAの仕様によるもの。バージョンの比較の際にはoldversionを使用する