質問

生のSQLを使用してカウンターを更新するカウンター関数があるとします:

 public void updateCounter() {
   executeSql("UPDATE counter SET count_value = count_value + 1 WHERE id = 1;");
 }

データベースは、カウンターへの2つの同時呼び出しが期待どおりに処理されることを確認します-すべての呼び出しが1つの増分でカウンターを更新し、更新が失われないこと。

生のSQLコマンドを発行してこれを実行するのではなく、GORMを使用します。単純な方法は、次のようなものです:

 public void updateCounter() {
   Counter c = Counter.get(1)
   c.countValue += 1
   c.save()
 }

この場合、2つのスレッドが同時にupdateCounter()メソッドを呼び出すと、更新が失われる可能性があると想定します。正しい「Grails / GORM-way」とは何ですか?この並行性の問題に対処するにはどうすればよいですか

役に立ちましたか?

解決

「悲観的」ロック戦略または「楽観的」ロック戦略のいずれかを使用できます。これは、HibernateとGORMの両方でサポートされています。デフォルトのGORM戦略は「optimistic」です(デフォルトで作成される永続的なドメインエンティティのバージョン列/プロパティを利用します)。次のように使用できます:

...
try {
 Counter c = Counter.get(1)
 c.countValue += 1
 c.save(flush:true)
}
catch(org.springframework.dao.OptimisticLockingFailureException e) {
// deal with concurrent modification here
}
...

代わりに「ペシミスティック」ロック戦略(他のすべての同時読み取りをブロックします)を好む場合は、明示的な「lock」GORMメタメソッドを使用して行うことができます。

...
Counter c = Counter.lock(1) //lock the entire row for update
c.countValue += 1
c.save(flush:true) //GORM will autorelease the lock once the TX is committed
...

これがお役に立てば幸いです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top