1

次のドメイン クラスがあるとします。

class Book {
    String name
    // more properties here, but name is the only one relevant for this example
}

ビューを介してその名前を更新したいと思います。次のフォームを使用して更新しています。

<g:form action="updateName" id="${book.id}">
    <g:hiddenField name="version"/>
    <g:textField name="name"/>
    ...
</g:form>

コントローラーでは、次のロジックを使用しています。

def updateName() {
    println("IN UPDATENAME()")
    def book = Book.get(params.id)
    println("VERSION BEFORE ASSIGN: ${book.version})
    book.version = params.long('version')
    println("VERSION AFTER ASSIGN: ${book.version})
    book.name = params.name
    book.save(flush: true)
    ...
}

2 つの異なるブラウザーで同じ編集ページを開いてテストしています。私はupdateName1つのブラウザで行い、次に別のブラウザで行います。2 番目updateNameは をスローする必要がありますが、OptimisticLockingFailureExceptionそうではありません。

SQL 出力を有効にすると、ログに次のように表示されます。

IN UPDATENAME()
VERSION BEFORE ASSIGN: 0
VERSION AFTER ASSIGN: 0
update book set version=?, name=? where id=? and version=?
binding parameter [1] as [BIGINT] - 1
binding parameter [2] as [STRING] - 'abc123'
binding parameter [3] as [BIGINT] - 1
binding parameter [4] as [BIGINT] - 0

IN UPDATENAME()
VERSION BEFORE ASSIGN: 1
VERSION AFTER ASSIGN: 0
update book set version=?, name=? where id=? and version=?
binding parameter [1] as [BIGINT] - 1
binding parameter [2] as [STRING] - 'def456'
binding parameter [3] as [BIGINT] - 1
binding parameter [4] as [BIGINT] - 1

つまり、2 番目の呼び出しでは、バージョンを 1 から 0 に正常に割り当てることができました。これにより、例外が発生するはずでしたが、何らかの理由で、SQL 呼び出しはバージョン = 0 ではなく 1 を正しくチェックしません。なぜこれが起こっているのか知っていますか?

4

1 に答える 1

0

version実際にはアクセサ メソッドとして定義されている Domain Class のプロパティ (フィールドではない) ですgetVersion()。に setterが定義されていませんversionDefaultGrailsDomainClass

scaffolded コントローラーの場合もversion、チェック/検証は手動で行われますが、 where プロパティが手動で設定されることはありません。オプティミスティック ロックは、セッション中flushにバージョンの不一致に遭遇したときに hibernate によって処理されます。不一致は、2 番目のユーザーがダーティ リードの被害者である場合にのみ発生します。

あなたの場合、バージョンを手動で検証してスキャフォールディングされたコントローラーロジックを収集する必要があるか、バージョンを手動で操作するのではなく、Hibernate に依存してジョブを実行する必要がありますが、これは実現不可能です。

于 2013-09-05T04:34:19.260 に答える