2010-11-25 12 views
103

Estaba recopilando información sobre el método flush(), pero no estoy muy claro cuándo usarlo y cómo usarlo correctamente. Según lo que leí, tengo entendido que los contenidos del contexto de persistencia se sincronizarán con la base de datos, i. mi. emitir estados pendientes o refrescar datos de la entidad.Uso correcto de flush() en JPA/Hibernate

Ahora tengo el siguiente escenario con dos entidades A y B (en una relación de uno a uno, pero no forzada o modelada por JPA). A tiene un PK compuesto, que se establece manualmente, y también tiene un campo de IDENTIDAD autogenerado recordId. Este recordId se debe escribir en la entidad B como clave externa al A. Estoy guardando A y B en una sola transacción. El problema es que el valor autogenerado A.recordId no está disponible dentro de la transacción, a menos que realice una llamada explícita de em.flush() después de llamar al em.persist() en A. (Si tengo una IDENTIDAD PK autogenerada, el valor se actualiza directamente en la entidad, pero no es el caso aquí).

¿Puede em.flush() causar daños al usarlo dentro de una transacción?

Respuesta

128

Probablemente los detalles exactos de em.flush() dependen de la implementación. En general, de todos modos, los proveedores de JPA como Hibernate pueden almacenar en caché las instrucciones de SQL que supuestamente deben enviar a la base de datos, a menudo hasta que realmente se compromete la transacción. Por ejemplo, si llama al em.persist(), Hibernate recuerda que tiene que hacer una base de datos INSERTAR, pero en realidad no ejecuta las instrucciones hasta que no haya confirmado la transacción. Afaik, esto se hace principalmente por motivos de rendimiento.

En algunos casos, de todos modos, desea que las instrucciones SQL se ejecuten inmediatamente; generalmente cuando necesita el resultado de algunos efectos secundarios, como una clave autogenerada o un activador de base de datos.

Lo que hace em.flush() es vaciar el caché interno de instrucciones SQL y ejecutarlo inmediatamente en la base de datos.

En pocas palabras: no se hace daño, solo se podría tener un rendimiento (menor) al sobrepasar las decisiones del proveedor JPA con respecto al mejor momento para enviar instrucciones SQL a la base de datos.

+1

Lo que él dijo. El comportamiento em.flush() hace eco de java.io.Flushable.flush() donde todos los datos almacenados en el búfer se envían a cualquier destino que sea apropiado. – Erik

+4

if flush() envía datos a la base de datos? ¿Qué sucede si se lanza una excepción después de eso? ¿El gerente de la entidad revertirá todo? incluso los datos escritos en el primer color? –

+88

flush() envía instrucciones SQL a la base de datos como INSERT, UPDATE, etc. No enviará COMMIT, por lo que si tiene una excepción después de un flush(), aún puede tener una reversión completa. – Flavio

0

En realidad, em.flush(), hace más que simplemente enviar los comandos SQL en caché. Intenta sincronizar el contexto de persistencia con la base de datos subyacente. Puede causar un gran consumo de tiempo en sus procesos si su caché contiene colecciones para sincronizar.

Precaución al usarlo.