12

コントローラ ロジック:

def updateObject() {

    Object o = Object.get(params.id as Long)

    o.otherObjects.clear()

    objectDataService.saveObject(o.id)

    OtherObject newObject = new OtherObject;

    o.addToOtherObjects(newObject)

    objectDataService.saveObject(o.id)

}

サービスロジック

def saveObject(long profileId) {
    o.save(flush:true)
}

何が起こるのですか

90% の場合、これで問題なく動作します。

問題

ERROR errors.GrailsExceptionResolver  - StaleObjectStateException occurred when processing request: [GET] /controller/updateObject - parameters:
stuff[]: data
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]. 
Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]

関連する質問を読み、merge上記の通話を見つけました。それはケースの約 50% を解決しましたが、すべてではありませんでした。

4

3 に答える 3

11

StaleObjectStateException:

この例外についてはすでにコメントアウトしています。無効なバージョン管理ドメイン オブジェクトがフラッシュ (明示的または暗黙的) 中にセッションにある場合、バージョン番号は増加しますが、データベースには保持されません。その後、再び有効になり、保存およびフラッシュされると、バージョン番号がデータベース内のバージョンと一致せず、StaleObjectStateException がスローされるため、hibernate はそれを古いと見なします。

これは次のように解決できます。

  1. 更新を行う前にバージョン値を調べる必要があります.1の場合は、プログラムを使用して更新する必要があります. アップデートの特定の操作で。
  2. @version アノテーションを使用する。

@バージョンについて:

楽観的ロックのバージョン番号メカニズムは、@Version アノテーションによって提供されます。例: @Version アノテーション

@Entity
public class Flight implements Serializable {
...
    @Version
    @Column(name="OPTLOCK")
    public Integer getVersion() { ... }
} 

ここでは、バージョン プロパティが OPTLOCK 列にマップされ、エンティティ マネージャーはそれを使用して競合する更新を検出し、last-commit-wins 戦略@versionによって上書きされる更新の損失を防ぎます。

Grails の詳細については、以下のリンクを参照してください。Git ハブ コードがあります。
GRAILS-8937 のテスト: HibernateOptimisticLockingFailureException

于 2014-09-03T13:25:16.487 に答える