2010-03-08 10 views
8

Un proyecto en el que estoy trabajando utiliza Spring 2.5 & JPA con Hibernate como proveedor.Invalidación de la sesión de JPA EntityManager

Mis clases DAO extienden JpaDaoSupport, entonces obtengo mi JpaTemplate usando el método getJpaTemplate().

La base de datos back-end puede ser modificada por mi aplicación o por una aplicación de terceros.

Cuando una aplicación de terceros cambia la base de datos (principalmente cambios en los datos de configuración), necesito proporcionarle una forma de invalidar todas las sesiones JPA y volver a cargar los datos nuevos (es decir, invalidar todas las sesiones de hibernación en el fondo). Esto debe ser "visto" por todos los usuarios simultáneos de mi aplicación.

¿Cómo puedo hacer esto?

Respuesta

21

Hay dos niveles de cachés:

  • primero nivel es propia caché del EntityManager.

    Puede refresh en una sola entidad y se volverá a cargar a partir de la base de datos, o puede clear el administrador de entidades en sí, en cuyo caso todas las entidades se eliminan de la memoria caché. No hay ninguna forma con JPA a evict only one specific entity desde el caché. Dependiendo de la implementación que use, puede hacer esto, p. Método de Hibernate evict.

  • El segundo nivel de almacenamiento en caché es el caché global.

    JPA 1.0 no proporcionó soporte para la memoria caché de segundo nivel. Entonces necesita confiar en la implementación específica subyacente o deshabilitarla. JPA 2.0 will address this issue con la anotación @Cache y la API de caché. Puede borrar la memoria caché de segundo nivel utilizando la API específica de Hibernate, p. SessionFactory.evict(...).

problemas con el almacenamiento en caché avanzadas son:

  • caché de consultas

    resultado de ciertas consultas se pueden almacenar en caché. De nuevo, no es compatible con él en JPA 1.0, pero la mayoría de las implementaciones tienen formas de especificar qué consulta se almacenará en caché y cómo.

  • Clustering

    Luego viene también el problema de sincronizar tedioso cachés entre nodos en un clúster. En este caso, esto depende principalmente de la tecnología de almacenamiento en caché utilizada, p. JBoss caché.

Su pregunta sigue siendo de alguna manera genérica y la respuesta dependerá de lo que esté haciendo exactamente.

Trabajé en un sistema donde se realizarían muchas actualizaciones sin pasar por hibernación, y finalmente desactivamos la memoria caché de segundo nivel.

Pero también puede realizar un seguimiento de todas las sesiones abiertas y, cuando sea necesario, desalojar todas las caché de primer nivel de todas las sesiones abiertas, más la caché de segundo nivel. Aún necesitaría administrar la sincronización usted mismo, pero me imagino que es posible.

+1

getJpaTemplate(). GetEntityManager(). Clear() hizo el truco. ¡Gracias! – dasp

1

Desde un punto de vista arquitectónico, no es una buena idea dejar que otras aplicaciones omitan toda la lógica de su negocio y modifiquen los datos persistentes. Hace temblar la tierra debajo de los pies de la aplicación de muchas maneras :)

¿No sería una buena idea integrarse con este otro sistema de una manera más elegante, por ejemplo mediante procesamiento de mensajes o procesamiento por lotes? . Spring tiene un gran apoyo para ambos.

+1

El problema de la invalidación de caché seguirá existiendo, por ejemplo, con el procesamiento por lotes y la actualización masiva. – ewernli

+2

Sí, así que diría que haga el procesamiento por lotes de tal manera que active eventos para aquellos objetos que necesitan ser invalidados. La combinación de Spring Integration y Spring Batch es perfecta para esto. Charla interesante: http://www.infoq.com/presentations/Automating-Operations –

Cuestiones relacionadas