Por qué necesita un caché de consultas

Reescribamos nuestro ejemplo con la obtención de empleados en HQL:

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

Los resultados de tales consultas no se almacenan ni en el caché de primer ni en el de segundo nivel.

Aquí es exactamente donde se puede utilizar la caché de consultas . También está deshabilitado por defecto. Para habilitarlo, agregue la siguiente línea al archivo de configuración:

<property name="hibernate.cache.use_query_cache" value="true"/>

Pero esto es sólo la mitad de la solución. Hemos habilitado el caché de consultas, pero también debemos especificar qué resultados de consulta queremos almacenar en caché. Esto debe escribirse en la consulta:

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

La caché de consultas es similar a una caché de segundo nivel. Pero, a diferencia de esto, aquí la clave de los datos del caché no es el identificador del objeto, sino el conjunto de parámetros de consulta. Y los datos en sí son los identificadores de los objetos que coinciden con los criterios de consulta. Por lo tanto, es racional usar este caché con el caché de segundo nivel.

Borrando el caché

Una de las tareas importantes cuando se trabaja con una memoria caché es asegurarse de que los objetos almacenados en la memoria caché cambien y se eliminen de la memoria caché (o se actualicen). Hibernate hace esto muy bien. A veces incluso parece que se guía por la regla "borrar el caché en cualquier situación incomprensible".

Supongamos que desea actualizar los datos del usuario a través de HQL:

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernate no puede saber exactamente qué ha cambiado en la base de datos, pero sabe que está cambiando un objeto Empleado. Por lo tanto, después de ejecutar esta consulta, Hibernate eliminará todos los objetos de tipo Empleado de su caché.

Pero NativeQuery funciona aún más interesante:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

Se ha ejecutado una consulta SQL nativa a la base de datos. Esto significa que algo ha cambiado en la base de datos: la solicitud se llamó en el método executeUpdate() . Por lo tanto, en este caso, Hibernate jugará a lo seguro y eliminará todos los objetos de todo tipo de su caché .

¿Qué le parece eso? ¡Llamas a una solicitud inofensiva e Hibernate en respuesta borra todos los datos del caché! Esto es ciertamente mejor que si mantuviera objetos que difieren de la base, ¡pero eso es todo!

Por lo tanto, los creadores de Hibernate descubrieron rápidamente cómo ayudar a Hibernate en este caso. Puede decirle qué tipo de entidad eliminar del caché:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
comentario _ Las consultas de selección nativas no vacían el caché , solo insertan, actualizan, eliminan, llaman a procedimientos, etc.

Borrado manual de caché

Por determinadas razones, es posible que desee eliminar un objeto de la memoria caché usted mismo. Esto se puede hacer de diferentes maneras.

nota _ Los objetos en el caché se almacenan en grupos llamados regiones . De forma predeterminada, el nombre de la región es el mismo que el nombre de la clase. Por lo tanto, si tiene objetos de tipo com.codegym.Employee , todos ellos se almacenarán en un grupo (región) con el nombre " com.codegym.employee ".

Si desea acceder al caché y hacer algo con él, puede hacerlo con el objeto SessionFactory y el método getCache() :

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

Si desea eliminar datos de todos los grupos (regiones), debe ejecutar la siguiente consulta:

session.getSessionFactory().getCache().evictAllRegions();

Para eliminar un objeto del caché, debe pasar su nombre (tipo) e identificación. Puede hacer esto de dos maneras:

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

También puede verificar si un objeto en particular está en el caché:

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);