En el siguiente ejemplo de código:

   Session session = getSessionFactory().openSession();

   MyObject currentState = (MyObject) 
           session.get(MyObject.class, id, new LockOptions(LockMode.???));

   if (!statusToUpdateTo.equals(currentState.getStatus())) {
     tx = session.beginTransaction();

     currentState.setStatus(statusToUpdateTo);
     session.save(currentState);

     tx.commit();
   }

   session.close();

Como se podría esperemos que interpretar el código, la idea es que compruebe nuestra tienda y encontrar un objeto con un determinado id, a continuación, actualizar a un determinado estado. Si nos encontramos con que el objeto está en el estado que se desea actualizar a, abandonamos hacer nada. De lo contrario, la actualización de la situación y volver a guardarlo en el almacén.

La preocupación que tengo es que lo que si varias de estas solicitudes a través de una sola vez, y todos tratamos de leer y actualizar el mismo objeto? Mirando a través de la doco parece Hibernar «generalmente obtiene exactamente el derecho de bloqueo de nivel automáticamente.» (LockMode.class), pero aún así estoy muy interesado en garantizar que sólo una cosa puede leer el objeto, tomar la decisión de que es necesario actualizar y, a continuación, actualizar – sin ningún otro tipo de hilos haciendo lo mismo a la misma entrada de base de datos.

De la LockMode clase I pensar PESSIMISTIC_WRITE es lo que yo busco, pero parece que no puede encontrar un recursos de documentación que lo confirma. Es alguien capaz de confirmar esto por mí, y que el código de arriba va a hacer lo que yo busco?

  • sí, usted quiere PESSIMISTIC_WRITE.
  • Gracias! Es bueno saber que estoy en el camino correcto. Así que supongo que nos lleva a otra pregunta, entonces cuando es que el bloqueo de la liberación? Me parece observar que se libera un bloqueo en commit(), pero, extrañamente, no parece ser liberados en la sesión.close()… Esto no tiene mucho sentido para mí – si no vas a commit() [es decir, en el caso de que no quiero entrar en si el de arriba] entonces, ¿cómo se forma explícita liberar el bloqueo?
  • en general, no de liberación de la base de datos de los bloqueos en una transacción una vez que ellos (no estoy seguro si dbs lo general, este). usted necesita ya sea para confirmar o deshacer la transacción para liberar el bloqueo. si usted tiene otro trabajo que necesita ser continuado, entonces usted probablemente necesita para manejar este bloqueo en una transacción independiente.
  • Que tiene sentido… supongo que el problema aquí es que el bloqueo es obtenida antes de que se inicia la transacción, si yo estoy siguiendo su terminología. He sido capaz de demostrar que cambiando el código anterior para incluir a una persona que comienza y luego se deshace de una transacción, el bloqueo se libera. Pero que apenas parece un poco… extraño para mí. Yo podría añadir una respuesta a mi propia pregunta que demuestra lo que hice y lo observado.
  • si usted no adquiere el bloqueo en un explícitamente controlada de la transacción, entonces usted realmente no tienen idea de cuánto tiempo de bloqueo estará en efecto. si su conexión db es el uso de alguna forma de auto-commit, usted podría perder el bloqueo en cualquier momento.
InformationsquelleAutor f1dave | 2013-09-13

1 Comentario

  1. 4

    Así que me di en mi código original que luego de la sesión de cierre, un bloqueo que todavía quedan en la base de datos, como las llamadas posteriores a eliminar las filas que yo había insertado no se completa cuando tx.commit() fue llamado en ellos.

    Después de añadir el siguiente bloque else, mi fase de pruebas que me inferir el sentido de que el bloqueo ha sido liberado (como estas filas están siendo limpiado).

       Session session = getSessionFactory().openSession();
    
       MyObject currentState = (MyObject) 
               session.get(MyObject.class, id, 
                           new LockOptions(LockMode.PESSIMISTIC_WRITE));
    
       if (!statusToUpdateTo.equals(currentState.getStatus())) {
         tx = session.beginTransaction();
    
         currentState.setStatus(statusToUpdateTo);
         session.save(currentState);
    
         tx.commit();
       } else {
         //Seems to clear lock
         tx = session.beginTransaction();
         tx.rollback();
       }
    
       session.close();

    A mí, obviamente, esto refleja mi falta de comprensión acerca de Hibernate mecanismos de cierre, pero se parece un poco extraño que uno puede obtener un bloqueo con la sesión.get(…) o de la sesión.de carga(…) y, a continuación, de no liberar un bloqueo con la sesión en sí, sino sólo a través de la creación de una transacción y cometiendo/a rodar de nuevo.

    Por supuesto, yo podría ser malentendido, el comportamiento observado 🙂

    • Hibernate doco acerca de Sesión.close(): Final de la sesión por la liberación de la conexión JDBC y la limpieza. y que no ha declarado nada acerca de la conexión, así que cuando usted cierra su sesión, es enteramente a su proveedor de conexión si o no y cuando comete (o rollos de la espalda) de la conexión. Es por eso que usted necesita para hacerlo a través de un TX de forma manual. Generalmente sesión es una unidad de su trabajo, que puede estar fuera de sincronización con la base de conexión.

Dejar respuesta

Please enter your comment!
Please enter your name here