talosのプログラミング教室

【Java・MyBatis】排他制御の実装方法

スポンサーリンク

こんにちは。talosです。

WebアプリからDBを更新するとき、2人以上のユーザーが同時に更新すると、データに不整合が起こります。

f:id:talosta:20201129174305p:plain

この現象を防ぐ手法としてよく使われるのが楽観的排他制御です。

この手法では、参照したときのバージョンや更新日時が更新時に変更されていないかを確認し、変更されていた場合は更新できないようにします。

f:id:talosta:20201130213153p:plain

この手法を実装していきたいと思います。

環境

言語:Java8
フレームワークJSF
DB:MySQL
O/Rマッピングツール:MyBatis

解説

まず、以下のようなテーブルを作りました。

f:id:talosta:20201129181911p:plain

updateDateは排他制御の判定に使います。


それではsrc/db/UserSample.javaを見ていきましょう。

注目してほしい点は一か所だけです。

example.createCriteria().andIdEqualTo(user.getId()).andUpdateDateEqualTo(user.getUpdateDate());

さらに言うとここだけ見ていただければよいです。

andUpdateDateEqualTo(user.getUpdateDate())

これは

WHERE UPDATE_DATE = 参照時点でのUPDATE_DATE

と同じです。

自身がデータを参照した後に他のユーザーが更新していた場合はデータに不整合が起こるため、更新できないようにする必要があります。

更新時にはUSER_SAMPLEテーブルのUPDATE_DATEを更新した日時に更新するため、他のユーザーが更新したかどうかは参照時点での更新日時(updateDate)とDBのUPDATE_DATEが一致しているかを確認すればわかります。

そこで自身が参照した時点での更新日時(updateDate)が現在の更新日時と同じかを確かめ、同じ場合のみ更新をします。


スポンサーリンク



実行

※ レコードは1つ以上挿入してください。

サーバーを立ち上げ、00.xhtmlを開きます。

また、シークレットウインドウでも00.xhtmlを開きます。

f:id:talosta:20201129184825p:plain

開けたら両方で同じ人の編集ボタンを押します。

すると、下のような画面が開きます。

f:id:talosta:20201129185140p:plain

片方の画面で名前を編集して実行します。

f:id:talosta:20201129185318p:plain

名前が変更されました。

f:id:talosta:20201129185432p:plain

もう片方の画面でも名前を編集して実行します。

f:id:talosta:20201129185602p:plain

こちらでは排他制御が行われ、エラーメッセージが出力されました。

f:id:talosta:20201129185636p:plain

おわりに

今回は排他制御を実装しました。

不明点があればコメントお願いします。