2012-05-10 13 views
7

Tengo problemas para entender de dónde obtiene la información la consulta HQL. Mi proyecto usa diferentes hilos y cada hilo lee/escribe en la base de datos. Los hilos no comparten objetos de Sesión, en su lugar estoy usando una clase HibernateUtil que crea sesiones para mí.Hibernate HQL solo golpea el caché de la sesión

Hasta hace poco, solo cerraba una sesión después de escribir, pero no después de leer. Los cambios en los objetos se verían inmediatamente en la base de datos pero al leer en otros hilos (diferente objeto de sesión que el utilizado para escribir) Me gustaría obtener información obsoleta. La lectura y la escritura ocurren siempre en diferentes hilos, lo que significa diferentes objetos de sesión y diferentes cachés de sesión.

siempre pensé que mediante el uso HQL en lugar de Criteria, yo siempre apuntar a la base de datos (o caché de segundo nivel) y no a la sesión de caché, pero al depurar el código, se hizo evidente para mí que el HQL estaba buscando el objeto en la memoria caché de la sesión y recuperó un viejo objeto desactualizado.

¿Estaba equivocado al suponer que HQL siempre apunta a la base de datos? ¿O al menos la memoria caché de segundo nivel?

PD: Estoy utilizando solo un objeto SessionFactory.

Respuesta

7

Hibernate tiene diferentes conceptos de almacenamiento en caché: cachés de entidades y cachés de consultas. El almacenamiento en caché de entidades es lo que hace el caché de sesión (y el caché de segundo nivel, si está habilitado).

Suponiendo que el caché de consultas no está habilitado (que no es, de forma predeterminada), entonces su HQL se habría ejecutado en la base de datos. Esto hubiera devuelto los ID de las entidades que coinciden con la consulta. Si esas entidades ya estaban en el caché de la sesión, entonces Hibernate las habría devuelto, en lugar de reconstruirlas desde la base de datos. Si su sesión tiene copias obsoletas (porque otra sesión ha actualizado la base de datos), ese es el problema que tiene.

Recomendaría no utilizar sesiones de larga duración, principalmente por esa razón. Debe limitar la duración de la sesión a la unidad de trabajo específica que está tratando de hacer, y luego cerrarla. Hay poco o nada de penalización en el rendimiento para hacerlo (suponiendo que utilice un grupo de conexiones de base de datos). Alternativamente, para asegurarse de no tener entidades obsoletas, puede llamar al Session.clear(), pero puede terminar con efectos secundarios inesperados de rendimiento.

+0

por lo que la primera vez que mi objeto de sesión realiza la consulta HQL se dirige a la base de datos. el resultado se almacena en el caché de la sesión. luego, la segunda vez que realizo la misma consulta HQL, lee el caché en lugar de apuntar a la base de datos. Este es el comportamiento predeterminado. ¿He entendido esto correctamente? ** ps: ** de hecho, el cierre de las sesiones después de cada lectura y escritura (objetos de corta duración 'Session') resuelve mi problema. – alegen

+4

@alegen: el HQL se ejecutará contra la base de datos * cada vez *, pero los objetos de Java que son el resultado final de esa consulta pueden provenir del caché de la sesión. Este es el comportamiento estándar. – skaffman

+1

usted señor tiene un gran día! Gracias por sus respuestas :) – alegen

Cuestiones relacionadas