3

複数のユーザーが同時に 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 が考えている間に起こった変更を見ていたら、おそらく別のことをしていたでしょう。

4

2 に答える 2

1

うまくいかないと感じる理由はsave(flush: true)?使いたくないですか、それとも何か他のことを考えていますか?

中に機能する楽観的ロックについて読んでおく必要がありますsave(flush: true)
version保存が成功したときにバージョンが更新されるように(フラッシュを使用して)ドメインクラスX。

ダーティ アップデートでは、アプリは次のようにスローOptimisticLockingFailureExceptionします。

def airport = Airport.get(10)
try {
    airport.name = "Heathrow"
    airport.save(flush: true)
}
catch (org.springframework.dao.OptimisticLockingFailureException e) {
    // deal with exception
}

上記のように例外を処理したくない場合は、ユーザー A のドメインを編集する前に、オブジェクト X の最新バージョンを取得するためにドメインを更新してから情報を更新してください。ただし、この方法はお勧めできません。長時間のセッション。

于 2013-09-18T00:53:04.797 に答える