2011-03-25 25 views
10

Quiero incrementar un campo en una tabla de base de datos en 1 usando Hibernate.Hibernar: Incrementar un campo entero

Puedo hacer esto simplemente cargando un objeto, incrementando el valor y actualizando el objeto. Sin embargo, si aparece otro hilo y actualiza el campo entre la carga y la actualización, el valor se dañará.

Así que en lugar que he llamado una actualización directamente en la base de datos:

Query updateHits = createQuery(
    "UPDATE Job SET hitCount = hitCount + 1 WHERE id = :jobId"); 
updateHits.setInteger("jobId", job.getId()); 
updateHits.executeUpdate(); 

Sin embargo, mi opinión es que esto no pasa por el bloqueo optimista en la base de datos y actualmente estoy experimentando un problema con los puntos muertos en el servidor SQL y creo este es el culpable

¿Hay alguna forma de incrementar un campo sin llamar directamente a la actualización y manteniendo la integridad de los datos?

+0

es posible que desee comprobar para ver cómo se crean los bloqueos. Si obtiene un bloqueo de tabla para esa actualización, algo anda mal. Si obtiene un bloqueo de fila, no veo cómo va a causar un punto muerto. – BlackICE

+0

En realidad, he logrado resolver el problema del interbloqueo simplemente asegurándome de que esta actualización sea la última instrucción que se ejecute dentro de la transacción. Sin embargo, todavía estoy interesado en conocer mejores soluciones. – 3urdoch

+1

su solución de "incremento por consulta" es diez veces mejor que lidiar con bloqueos pesimistas, especialmente si está trabajando en transacciones múltiples y de larga ejecución – kommradHomer

Respuesta

3

puedo hacer esto simplemente cargando un objeto , incrementando el valor y actualizar el objeto, sin embargo si otro hilo viene y actualiza el campo de entre la carga y la actualización entonces el valor se convertirá corrupto.

Si el segundo hilo también está utilizando hibernate y está utilizando el control de versiones de hibernación (@Version), el único hilo que confirma primero y cambia el objeto establecerá la nueva versión en el objeto.

Cuando entra la confirmación del segundo hilo, hibernate verificará si falla el bloqueo optimista y emitirá una excepción - StaleObjectException si no me equivoco. Si bloqueas tu código concurrente, tendrás la oportunidad de cargar el objeto nuevamente y probar tu actualización si tiene sentido. Si está utilizando JPA, se lanzará una OptimisticLockException.

Hay un montón de información en el Hibernate Optimistic Concurrency Control Section.

¡Salud!

Cuestiones relacionadas