Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

451
Vistas
Hibernate: bloquea una fila durante la actualización, para que el usuario no recupere un contador de ella

Estoy trabajando en un proyecto Spring-MVC en el que estoy usando Hibernate como ORM, PostgreSQL como nuestra base de datos y en uno de nuestros Objetos (GroupCanvas), tenemos un número que se incrementa cada vez que el usuario realiza alguna acción, y luego el El objeto GroupCanvas se actualiza en la base de datos y debe ser único.

El problema que tenemos actualmente es que, si varios usuarios toman medidas en el front-end, algunos de ellos obtienen números duplicados. Estamos trabajando para arreglar esto ahora, para que luego podamos implementar una secuencia y estar seguros de que los números son únicos.

¿Cómo puedo asegurarme de que cuando estoy actualizando la fila, otros usuarios estén esperando hasta que se actualice la fila? Probé LockMode.Pessimistic_write, y algunos otros, ninguno ayudó.

Código:

 @Override public void incrementNoteCounterForGroupCanvas(int canvasId) { Session session = this.sessionFactory.getCurrentSession(); session.flush(); Query query = session.createQuery("update GroupCanvas as gc set gc.noteCount=gc.noteCount+1 where gc.mcanvasid=:canvasId"); query.setParameter("canvasId",canvasId); query.executeUpdate(); session.flush(); } @Override public GroupCanvas getCanvasById(int mcanvasid) { Session session = this.sessionFactory.getCurrentSession(); session.flush(); return (GroupCanvas) session.get(GroupCanvas.class, mcanvasid,LockMode.PESSIMISTIC_WRITE); }

Ambos métodos están en DAO, que tiene anotación @Transactional y anotación presente en la capa de servicio también.

Gracias.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Mirando el método que ha publicado el uso si la técnica de 'BLOQUEO' no es del todo correcta. Para que un bloqueo termine con el resultado que está buscando, la secuencia de acciones debe ser similar a las siguientes (en pocas palabras, es similar al bloqueo de doble verificación pero implementado mediante bloqueos DB - https://en .wikipedia.org/wiki/Double-checked_locking ).

  1. Inicie la transacción (por ejemplo, anotación @Transactional en su método de servicio)
  2. Recupere la entidad de la base de datos con el modo de bloqueo PESSIMISTIC_WRITE (asegúrese de indicar en hibernación que se debe leer una copia nueva en lugar de la almacenada en la memoria caché de la sesión)
  3. Si es necesario, verifique el valor actual del campo de destino si cumple con sus invariantes
  4. Realizar el cambio/actualización en el campo (por ejemplo, incrementar el valor de un campo)
  5. Guarde la entidad (y asegúrese de vaciar el valor en la base de datos si no quiere esperar a que se vacíe automáticamente)
  6. Confirmar la transacción (hecho automáticamente cuando se usa @Transactional )

La diferencia esencial de esta secuencia en comparación con el método publicado es que la actualización del valor de la propiedad se realiza mientras su transacción mantiene un bloqueo en la fila de entidad/base de datos de destino , lo que evita que otras transacciones lo lean mientras su actualización está en curso.

Espero que esto ayude .

ACTUALIZACIÓN: Creo que algo así como el siguiente fragmento de código debería funcionar como se esperaba:

 @Transactional @Override public void incrementNoteCounterForGroupCanvas(int canvasId) { final Session session = this.sessionFactory.getCurrentSession(); final GroupCanvas groupCanvas = session.get(GroupCanvas.class, canvasId,LockMode.PESSIMISTIC_WRITE); session.refresh(groupCanvas); groupCanvas.setNoteCount(groupCanvas.getNoteCount()+1); session.saveOrUpdate(groupCanvas); session.flush(); }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda