java - saveorupdate - Hibernate Session flush comportamiento
saveorupdate hibernate example (6)
Yo uso Spring e Hibernate en una aplicación web,
SessionFactory se inyecta en un bean DAO, y luego este DAO se usa en un Servlet a través de webservicecontext.
Los métodos DAO son transaccionales, dentro de uno de los métodos que uso ... getCurrentSession (). Save (myObject);
Un servlet llama a este método con un objeto pasado.
Parece que la actualización no se ha vaciado a la vez , se tarda unos 5 segundos en ver los cambios en la base de datos. El método del servlet en el que se llama el método de actualización de ese DAO, tarda una fracción de segundo en completarse.
Después de que se complete el método @Transactional de DAO, ¿NO puede suceder la descarga? No parece ser una regla [ya lo veo].
Entonces la pregunta es: ¿qué hacer para forzar que la sesión se desactive después de cada método DAO? Puede que no sea algo bueno, pero al hablar de una capa de Servicio, algunos métodos deben terminar con una descarga inmediata, y el comportamiento de Hibernate Session no es predecible.
Entonces, ¿qué hacer para garantizar que mi método @Transactional persista todos los cambios después de la última línea de ese código de método?
getCurrentSession().flush() is the only solution?
ps. Leí en algún lugar que @Transactional está asociado con una Transacción DB. Método devuelto, la transacción debe ser confirmada. No veo que esto suceda.
¡Yo tuve este problema también! Estoy usando la transacción de anotación de Spring (@Transactional) y estoy obteniendo un método que realmente está ejecutando session.flush (), ¡y otros no!
De mi registro de depuración tengo:
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
Se debe llamar a session.close () desde Spring TransationManager, pero no estoy seguro de lo que está pasando: revisé mi configuración de Spring y no puedo argumentar por qué está sucediendo esto. Sigo investigando y volveré a publicar cualquier sugerencia, pero si alguien tiene algún consejo útil, estaré muy agradecido: o)
Actualización: el problema parece estar relacionado con el modo de descarga de la sesión de hibernación = MANUAL: no descargó los objetos al final de la transacción de Spring.
Puedes verificar tu modo de descarga actual con algo como:
SessionFactoryUtils.getSession(mySessionFactory(), false).getCurrentSession().getFlushMode()
ACTUALIZACIÓN [RESUELTOS PARA MÍ]:
Busqué mucho en mi problema y encontré el origen del problema y una solución alternativa.
Tuve, como tú si lo entiendo bien, un problema intermitente en el que algunas transacciones se cerraron correctamente (es decir, se eliminaron las sesiones de hibernación) y otras no.
Descubrí que:
el problema se debió a que
flushMode
configuró enFlushMode.MANUAL
cuandoFlushMode.MANUAL
a la transacción (que no desencadena la operación deFlushMode.MANUAL
cuando se confirma la transacción);esto, a su vez, se debió a que sucedió algo desagradable entre Spring y ZK (las malas transacciones fueron todas de los compositores de ZK; si no conoces a ZK, se llaman de servlets, aproximadamente equivalentes a las acciones de Struts);
El problema preciso radica en que el
OpenSessionInViewFilter
de Spring no se comunica correctamente con los filtros de ZK: la sesión de Hibernate proporcionada porOpenSessionInViewFilter
no está configurando correctamente su modo de descarga. El único compositor de ZK funciona bien (lo he probado en algunas pruebas de JUnit), así como elOpenSessionInViewFilter
solo (lo he probado en un Servlet simple utilizandoWebApplicationContextUtils
).
Conclusión: Llamo a session.flush()
al final de cada método @Transactional en mis compositores, y migraré a Vaadin (parece mucho más sencillo de integrar).
No recomendaría el uso de hibernate.transaction.flush_before_completion globalmente por razones de rendimiento.
Alternativamente, puede gestionar las transacciones usted mismo:
@PersistenceContext
private EntityManager em;
....
public void save(){
try
{
em.getTransaction().begin();
<update database>
em.getTransaction().commit();
}
catch(Throwable th) {
em.getTransaction().rollback();
//log, rethrow
}
}
Para sus necesidades particulares (descarga en cada llamada de método DAO), puede configurar el modo de descarga de sesión en FlushMode.ALWAYS. De la documentación de hibernación:
The Session is flushed before every query.
Sorprendentemente, creo que esta es la respuesta exacta que puede resolver tal situación exacta, puede usar FlushMode.ALWAYS
para un DAO en particular cada vez que necesite vaciar la sesión y restringir completamente después de cada transacción.
@Autowired
private SessionFactory sessionFactory;
@Before
public void myInitMethod(){
sessionFactory.getCurrentSession().setFlushMode(FlushMode.ALWAYS);
}
ALWAYS
flushmode no es preferible porque es costoso, pero como usted lo requiere, puede tener varias sesiones de fábrica con diferentes modos de flush para diferentes requisitos.
Una vez que se haya completado el método @Transactional de "nivel superior" (es decir, el método llamado desde su servlet), la transacción se debe confirmar y el comportamiento predeterminado de Hibernate es eliminar la confirmación.
Parece que algo extraño está sucediendo y deberías investigar un poco.
Investigue sus registros, en particular, establecería el nivel de registro en DEBUG en su Administrador de transacciones para ver exactamente lo que está haciendo el administrador de transacciones.
Además, establezca el inicio de sesión para hibernación (establezca show_sql en verdadero): esto se enviará a System.out cuando se produzca un lavado y esto podría darle algunas pistas.
Informe si encuentra algo interesante.
establecer la propiedad "hibernate.transaction.flush_before_completion" en true podría ayudar.
<prop key="hibernate.transaction.flush_before_completion">true</prop>
https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/
"Si está habilitada, la sesión se vaciará automáticamente durante la fase anterior a la finalización de la transacción. Se prefiere la administración integrada y automática del contexto de la sesión, consulte la Sección 2.5," Sesiones contextuales "".