複数のユーザーが同時に Web ブラウザーでモデルを編集できるようにし、保存時に競合が検出されるようにしたい (最初に書き込みを行ったユーザーが、2 番目のユーザーが明示的にそう言わずに変更を上書きしないようにするため)。次に例を示します。
ユーザー A はオブジェクト X を取得し、ブラウザーでそれを見ています。
次に、ユーザー B がオブジェクト X を取得し、ブラウザーで確認して変更し、保存すると、Grails の REST API に投稿さsave
れ、モデルがデータベースに投稿されます。
次に、ユーザー A がオブジェクトを変更して保存します。
ユーザー A がオブジェクト X を取得してからオブジェクト X が変更されたことをアプリケーションに検出させ、ユーザー A に適切なメッセージといくつかのオプションを表示します。
モデルが変更されたかどうかはどうすればわかりますか? isDirty
動作せず、動作しないことに注意してくださいsave(flush:true)
。
アップデート
Optimistic Locking と、送信後のモデル変更の検出について説明している回答がいくつかあります。ユーザーが取得した後の変更を検出したい。もう一度質問を読んでください。
ここで、楽観的ロックが上記の問題を解決しない理由を明らかにします。ただし、楽観的ロックを使用する方法があるかもしれないと想像できますが、以下の回答とドキュメントに記載されているように、役に立ちません。理由は次のとおりです。
楽観的ロックは、リクエスト全体ではなく、リクエスト内で機能します。最初のユーザーからの更新要求の進行中に 2 番目のユーザーがオブジェクトを更新した場合、楽観的ロックにより、1 人のユーザーのみが更新を実行できます。オプティミスティック ロックは、同じ要求で別の読み取り-変更-書き込みとインターリーブされる読み取り-変更-書き込みから保護します。以下は、楽観的ロックが保護するイベントの時系列 (時間は上から下) です。
User 1 User 2
presses submit presses submit
in update action
| read model
| in update action
| | read model
| | modify model
| | write model
| return
| modify model
| write model - FAILS
return error or something
最初のユーザー投稿によるモデルの書き込みは失敗します。これは、レコードが読み取られてから変更されたことが楽観的ロック チェックによって検出されるためです。
私が保護したいのは、次のタイムラインです。
User 1 User 2
visits web app visits web app
clicks link to edit model clicks link to edit model
in edit action
| read model
| render model
return
in edit action
| read model
| render model
return
user edits model user edits model
user thinks... hmm... user submits
in update action
| read model
| modify model from params
| write model
return
user submits
in update action
| read model
| modify model from params
| write model - OOPS! overwrote previous changes
return
この例から、ユーザー 1 がユーザー 2 の変更を上書きすることがわかります。しかし、ユーザー 1 は、データベースからのモデルの古いコピーに基づいて変更を加えました。ユーザー 2 が考えている間に起こった変更を見ていたら、おそらく別のことをしていたでしょう。