java hibernate collections transactions ehcache

java - Hibernate/Ehcache: desalojando colecciones de caché de segundo nivel no sincronizadas con otras lecturas de DB



collections transactions (3)

¿Por qué no puedes mantener las colecciones al día? es decir, cuando agrega un objeto, agregue el objeto a la colección a la que pertenece. Cuando elimina un objeto, elimínelo de la colección en la que se encuentra. Según mi experiencia al utilizar un caché con hibernación o jpa, el estado del objeto (no el estado de la base de datos) se almacena en caché, por lo que debe asegurarse de que su modelo de objetos en la memoria está sincronizado con el modelo de objetos en la base de datos.

¿O me estoy perdiendo algo? ¿Por qué no puedes simplemente mantener las colecciones al día?

Tengo una aplicación que usa JPA, Hibernate y ehcache, así como las transacciones declarativas de Spring. La carga en DB es bastante alta, por lo que todo se almacena en caché para acelerar las cosas, incluidas las colecciones. Ahora no es un secreto que las colecciones se almacenan en caché por separado de las entidades que las poseen, así que si elimino una entidad que es un elemento de dicha colección en caché, persistiré una entidad que debe ser un elemento de uno, o actualizaré una entidad tal que viaja de una colección a otra, tengo que realizar el desalojo a mano.

Así que uso un oyente de eventos de hibernación que realiza un seguimiento de las entidades que se insertan, eliminan o actualizan y guarda esa información para una sincronización de transacciones registrada con el administrador de transacciones de Spring para actuar. La sincronización realiza el desalojo una vez que se ha comprometido la transacción.

Ahora el problema es que con bastante frecuencia, algunas otras transacciones concurrentes logran encontrar una colección en el caché que acaba de ser desalojada (estos eventos suelen estar separados por décimas de segundo de acuerdo con el registro) y, naturalmente, hace que ocurra una EntityNotFoundException.

¿Cómo sincronizo esto correctamente?

Intenté realizar el desalojo en cada uno de los 4 métodos de TransactionSynchronization (que se invocan en diferentes momentos en relación con la finalización de la transacción), pero no ayudó.


Esencialmente, lo que debe hacer es forzar una lectura de la base de datos en el caso de que una colección esté en proceso o haya sido desalojada. Una forma de hacerlo sería marcar la colección como sucia tan pronto como se haya recibido una solicitud para desalojarla, pero antes de ingresar a la transacción para cambiarla. Cualquier transacción concurrente que se presente comprobará la bandera sucia y si está configurada como verdadera, debería obtener los datos de la base de datos, de lo contrario, puede leerlos desde la memoria caché. Es posible que deba cambiar la configuración de la transacción de su base de datos para que las transacciones simultáneas se bloqueen hasta que termine la actualización de los datos para que se lean los datos correctos de la base de datos. Una vez que finaliza la transacción, puede restablecer la bandera sucia a falso.

También puede crear un bloqueo en la colección en caché cuando una actualización, inserción o eliminación se vence mientras dure el desalojo. Esto asegurará que ninguna otra transacción pueda leer / cambiar la colección en caché hasta que finalice el proceso de desalojo.