Pergunta

Vamos dizer que tenho uma função de contador que atualiza um contador usando SQL puro:

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

O banco de dados seria certificar-se de que duas chamadas simultâneas para o contador são tratados como esperado -. Que todas as chamadas iria atualizar o contador com um incremento e nenhuma atualização iria se perder

Ao invés de executar isso emitindo um comando SQL cru que eu gostaria de usar GORM. A maneira ingênua de fazê-lo seria algo ao longo das linhas de:

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

Neste caso eu supor que uma atualização poderiam ser perdidos se dois threads chamar o método updateCounter () no mesmo momento. Qual é o "Grails / GORM-maneira" correta para lidar com este problema de concorrência?

Foi útil?

Solução

Você pode usar tanto 'pessimistas' ou 'otimistas' bloqueio estratégias, que ambos suportados pelo Hibernate e, portanto, por GORM. A estratégia GORM padrão é 'otimista' (que utiliza a coluna de versão / propriedade da entidade de domínio persistente, criado por padrão). Pode ser usado como este:

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

Se você preferir a estratégia de bloqueio 'pessimista' em vez (que irá bloquear todos os outros concorrentes lê, btw), você poderia fazê-lo usando 'lock' explícita GORM meta-método, assim:

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

Espero que isso ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top