Concurrency bei der Verwendung von GORM in Grails
-
03-07-2019 - |
Frage
Lassen Sie uns sagen, dass ich eine Zählerfunktion haben, die einen Zähler mit rohen SQL aktualisiert:
public void updateCounter() {
executeSql("UPDATE counter SET count_value = count_value + 1 WHERE id = 1;");
}
Die Datenbank würde sicherstellen, dass zwei gleichzeitige Anrufe an den Zähler behandelt werden wie erwartet -., Dass alle Anrufe den Zähler mit einem Zuwachs und kein Updates würde verloren gehen aktualisieren würden
Anstatt diese Ausführung durch einen rohen SQL-Befehl Ich mag GORM verwenden. Die naive Art und Weise zu tun, es wäre etwas entlang der Linien der folgenden sein:
public void updateCounter() {
Counter c = Counter.get(1)
c.countValue += 1
c.save()
}
In diesem Fall würde ich davon ausgehen, dass ein Update verloren gehen könnte, wenn zwei Threads die updateCounter () -Methode im selben Moment nennen. Was ist die richtige "Grails / GORM-way" diese Gleichzeitigkeit Problem zu behandeln?
Lösung
Sie können entweder ‚pessimistisch‘ oder ‚optimistisch‘ Sperrstrategien verwenden, die sowohl von Hibernate unterstützt und daher von GORM. Die Standard-GORM Strategie ist ‚optimistisch‘ (die die Version Spalte / Eigenschaft der persistenten Domäne Entität verwendet, standardmäßig erstellt). Es könnte wie folgt verwendet werden:
...
try {
Counter c = Counter.get(1)
c.countValue += 1
c.save(flush:true)
}
catch(org.springframework.dao.OptimisticLockingFailureException e) {
// deal with concurrent modification here
}
...
Wenn Sie die ‚pessimistische‘ Locking-Strategie bevorzugen statt (die blockiert alle anderen gleichzeitig liest, btw), können Sie es tun könnte explizite ‚lock‘ GORM Meta-Methode verwendet, etwa so:
...
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
...
Hope, das hilft.