2

生の 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」は何ですか?

4

1 に答える 1

7

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

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

代わりに「悲観的な」ロック戦略を好む場合 (他のすべての同時読み取りをブロックします)、次のように明示的な「ロック」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
...

お役に立てれば。

于 2009-03-06T15:09:49.893 に答える