Параллельность при использовании GORM в Grails - PullRequest
2 голосов
/ 06 марта 2009

Допустим, у меня есть функция счетчика, которая обновляет счетчик с использованием необработанного SQL:

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

База данных будет гарантировать, что два одновременных вызова счетчика будут обрабатываться, как и ожидалось, - что все вызовы будут обновлять счетчик с одним шагом, и обновления не будут потеряны.

Вместо того, чтобы выполнить это, введя сырую команду SQL, я бы хотел использовать GORM. Наивным способом сделать это было бы что-то вроде:

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

В этом случае я бы предположил, что обновление может быть потеряно, если два потока вызовут метод updateCounter () одновременно. Что такое правильный путь Grails / GORM для решения этой проблемы параллелизма?

1 Ответ

6 голосов
/ 06 марта 2009

Вы можете использовать «пессимистическую» или «оптимистическую» стратегию блокировки, которая поддерживается 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
...

Надеюсь, это поможет.

...