Question

Disons que j’ai une fonction de compteur qui met à jour un compteur en utilisant du SQL brut:

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

La base de données s'assurera que deux appels simultanés au compteur sont traités comme prévu - tous les appels mettront à jour le compteur avec un incrément et aucune mise à jour ne sera perdue.

Plutôt que de l'exécuter en émettant une commande SQL brute, j'aimerais utiliser GORM. La façon naïve de le faire serait quelque chose comme:

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

Dans ce cas, je suppose qu'une mise à jour peut être perdue si deux threads appellent la méthode updateCounter () au même moment. Quelle est la réponse correcte "Grails / GORM-way" pour gérer ce problème de concurrence?

Était-ce utile?

La solution

Vous pouvez utiliser des stratégies de verrouillage "pessimistes" ou "optimistes", qui sont toutes deux prises en charge par Hibernate et donc par GORM. La stratégie GORM par défaut est «optimiste» (qui utilise la colonne version / propriété de l'entité de domaine persistant, créée par défaut). Il pourrait être utilisé comme ceci:

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

Si vous préférez la stratégie de verrouillage "pessimiste" (qui bloquera toutes les autres lectures simultanées, d'ailleurs), vous pouvez le faire en utilisant une méta-méthode explicite "lock" GORM, comme suit:

...
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
...

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top