Una mejora conveniente en una aplicación con acceso a base de datos, es 'cachear' aquellas consultas más comunes.
En este post vamos a tratar de como configurar la una aplicación base con JPA, Spring e Hibernate. Donde haremos uso del cache para almacenar objetos pero solo en modo lectura (muy válido por ejemplo para la tabla PAISES o PROVINCIAS). Indicaremos cuales son los pasos clave y por último veremos los resultados de su correcto funcionamiento.
El código de la aplicación lo podéis obtener aquí.
El código de la aplicación lo podéis obtener aquí.
- Configuración Base
La aplicación tiene JPA 2.0, Hibernate 3.6.7 y Spring 3.0.6. Por lo tanto tendremos un fichero de configuración de Spring, donde configuraremos un EntityManager y su correspondiente TransactionManager, un fichero persitence.xml con la configuración de acceso a datos. La idea del proyecto es que tenga la menos configuración posible de ahí el uso de 'JpaDaoSupport' en los DAO o el uso de anotaciones.
- Configuración JPA
Lo más importante es indicar el modo de utilización del cache: ALL (todas las clases JPA), NONE (ninguna), ENABLE_SELECTIVE (aquellas que se han configurado explícitamente con @Cacheable) y DISABLE_SELECTIVE (todas menos las que se han configurado explícitamente con @Cacheable(false)).
Luego tenemos que indicar cual será la
clase encargada de la gestión de la cache. Esto lo podemos hacer a
través de la propiedad: 'hibernate.cache.region.factory_class'.
Y
por último indicar que queremos que sea usado el sistema de cache a
través de las propiedades: 'hibernate.cache.use_query_cache' y
'hibernate.cache.use_second_level_cache'.org.hibernate.ejb.HibernatePersistence ENABLE_SELECTIVE
- Configuración Java
Necesitamos indicar en las clases JPA que queremos que sean tenidas en cuenta por la cache en el modo 'ENABLE_SELECTIVE'. Para ello añadimos la anotación javax.persistence.Cacheable. Esta anotación nos permite según en la posición donde la pongamos si vamos a cachear un método o una clase entera o indicar el gestor de la cache (si no queremos usar el de por defecto) o que se realice el 'cacheo' solo bajo una determinadas circunstancias. Aquí puedes leer más.
@Entity @Table(name = "libro", catalog = "almacen") @Cacheable public class Libro implements java.io.Serializable {
- Ejemplo
El ejemplo lo vamos a realizar accediendo dos veces a un determinado objeto de BBDD de dos formas distintas. En un primera vez sin tener cache, y una segunda vez con la cache configurada.
Salida 1:
#VALORES INICIALES
Contains libro 25: false
EntityFetchCount: 0#PRIMER ACCESO
Hibernate: select libro0_.IDENT as IDENT0_0 from almacen.libro libro0_ where libro0_.IDENT=?
time findById(25): 52
EntityFetchCount: 0
Contains libro 25: false
Second level stats = 0, 0, 0#SEGUNDO ACCESO
Hibernate: select libro0_.IDENT as IDENT0_0 from almacen.libro libro0_ where libro0_.IDENT=?
time findById(25): 2
EntityFetchCount: 0
Contains libro 25: false
Second level stats = 0, 0, 0
Salida 2:
#VALORES INICIALES
Contains libro 25: false
EntityFetchCount: 0#PRIMER ACCESO
Hibernate: select libro0_.IDENT as IDENT0_0 from almacen.libro libro0_ where libro0_.IDENT=?
time findById(25): 70 ms
EntityFetchCount: 0
Contains libro 25: true
Second level stats = 1, 0, 1
#SEGUNDO ACCESO
time findById(25): 1 ms
EntityFetchCount: 0
Contains libro 25: true
Second level stats = 1, 1, 1
Como podemos ver en la salida 1 (Sin cache) para acceder por segunda vez al objeto, volvemos a consultar en BBDD, lo que no hacemos en la salida 2. Aparte de que el acceso a dicho objeto es mucho más rápido.
Dos apuntes más:
- Mediante la propiedad del fichero persistence.xml 'net.sf.ehcache.configurationResourceName' podemos indicar un fichero con la configuración que le queramos dar al ehcache. Por si queremos sobrescribir la de por defecto. Aquí puedes leer más.
- Si utilizamos Hibernate 3 (3.3 o superior) debemos utilizar como clase de factoría 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory' y 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory' para Hibernate 4.
No hay comentarios:
Publicar un comentario