Pregunta

Supongamos que tengo una función de contador que actualiza un contador utilizando SQL sin formato:

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

La base de datos se aseguraría de que dos llamadas simultáneas al contador se manejen como se esperaba, que todas las llamadas actualizarían el contador con un incremento y que no se perderían actualizaciones.

En lugar de ejecutar esto emitiendo un comando de SQL sin procesar, me gustaría usar GORM. La mejor manera de hacerlo sería algo como:

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

En este caso, asumo que una actualización podría perderse si dos subprocesos llaman al método updateCounter () en el mismo momento. ¿Cuál es la correcta " Grails / GORM-way " para manejar este problema de concurrencia?

¿Fue útil?

Solución

Puede utilizar estrategias de bloqueo "pesimistas" u "optimistas", ambas compatibles con Hibernate y, por lo tanto, con GORM. La estrategia GORM predeterminada es "optimista" (que utiliza la columna / propiedad de la versión de la entidad de dominio persistente, creada de forma predeterminada). Podría ser usado así:

...
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 prefieres la estrategia de bloqueo 'pesimista' (lo que bloqueará todas las demás lecturas concurrentes, por cierto), puedes hacerlo utilizando el metamétodo GORM de 'bloqueo' explícito, como por ejemplo:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top