Allan Larangeiras

Analista de Sistemas




read

Chamamos de cache de segundo nível pois o Hibernate já possui o cache em nível de sessão. Esta estratégia é utilizada quando existe a necessidade de um excessivo acesso à uma entidade que possui pouca atualização. Nesse caso o estado da mesma se mantém quase que estático, não necessitando acesso excessivo ao banco. O Cache L2 age armazenando em memória os objetos consultados onde os mesmo podem ser recuperados de lá através do seu atributo-chave.

Query Cache

O Query Cache é uma extensão do Cache L2. Utilizamos o mesmo para otimizar certas consultas cujos parâmetros se repetem constantemente. O cache não age armazenando o resultado da consulta e sim os resultados dos atributos-chave da mesma. Uma vez de posse desses dados na próxima vez que a consulta for executada com o mesmo parâmetro, o sistema de cache irá utilizar as chaves para efetuar o load dos objetos diretamente da memória.

EhCache

O EhCache é um projeto Open Source mantido inicialmente pela mesma equipe que criou o Hibernate. Por este motivo é sistema de cache mais recomendado de se utilizar em conjunto com o mesmo.

O EhCache não é a única ferramenta disponível para tal. Podemos encontrar outras soluções como OSCache, SwarmCache e o Jboss Cache.

Também possibilita fazer cache em disco. Uma vez que uma certa quantidade de memória seja consumida (conforme foi parametrizado) e o cache em disco esteja habilitado, o EhCache chaveará para o cache em disco. Por default este cache é feito no diretório temporário do sistema operacional (identificado pela variável de ambiente java.io.tmpdir).

Configurando o Maven

É fácil configurar o EhCache para ter as suas dependências resolvidas pelo maven

Adicione as tags abaixo dentro do elemento do seu arquivo pom.xml

<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>1.6.1</version>
</dependency>

Após isso rode o maven conforme na linha abaixo:

mvn clean compile install dependency:copy-dependencies

Configurando o Spring

Primeiramente configure o Hibernate para que ele reconheça o EhCache e habilite o Caching L2 e o QueryCache:

<util:properties id="hibernateProperties">
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
</util:properties>

Acima foi utilizado o mapeamento das propriedades do hibernate para habilitar o cache.

Para configurar o EhCache no Spring, faça conforme abaixo:

     <bean>
<property name="staticMethod" value="java.lang.System.setProperty" />
<property name="arguments">
<list>
<value>ehcache.disk.store.dir</value>
<value>{PATH PARA O CACHE EM DISCO}</value>
</list>
</property>
</bean>

<!-- Configuração do EhCache no Spring -->
<bean id="defaultCache">
<property name="cacheName" ><value>org.hibernate.cache.StandardQueryCache</value></property>
<property name="cacheManager" ref="cacheManager" />
<property name="maxElementsInMemory" ><value>{ QUANTIDADE DE OBJETOS NA MEMÓRIA }</value></property>
<property name="eternal" ><value>false</value></property>
<property name="timeToLive" ><value>{ TEMPO DE VIDA DO CACHE EM SEGUNDOS }</value></property>
<property name="overflowToDisk" ><value>{ FLAG QUE INDICA SE SERÁ USADO O CACHE EM DISCO OU NÃO }</value></property>
</bean>

<!-- Manager do EHCache, é responsável por representar uma arquivo ehcache.xml -->
<bean id="cacheManager">
<property name="cacheManagerName" value="CacheManager" />
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>

Ao configurar o cacheName, este será utilizado como atributo QUERY REGION no momento de configurar o query cache. Case utilize como cacheName o valor org.hibernate.cache.StandardQueryCache o Hibernate irá subentender que todas as queries cache não nomeadas utilizarão esta configuração de cache. Logicamente não devemos ter duas configurações com o mesmo nome.

Configuração do EhCache/Hibernate

Ehcache.xml

Crie no seu classpath (recomendo que seja dentro do seu diretório de resources) um arquivo nomeado como ehcache.xml e com o seguinte conteúdo.

<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

<diskStore path="ehcache.disk.store.dir"/>

<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"

/>

</ehcache>

O arquivo de cache é necessário para mapear a variável de ambiente do path do cache em disco e para definir um cache default, mesmo que este arquivo não seja definido o EhCache necessita do mesmo. Na ausência o EhCache irá utilizar o arquivo ehcache-failsafe.xml direto de dentro do jar da API.

Mapeando as entidades

Abaixo encontramos o mapeamento da entidade para que a mesma utilize o cache L2 puro e simples. Uma vez mapeada os objetos serão cacheados em memória e recuperados através do load (que necessita do atributo-cache do mesmo) desde que dentro do tempo de vida do cache (TIME TO LIVE – configurado no arquivo de contexto do Spring).

@Entity
@Table(name="ENTITY")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Entity implements Serializable {

}

Os tipos de estratégias utilizadas pelo cache otimizam o cache para situações específicas. Segue abaixo os suportados pelo EhCache:

  • READ_ONLY – Otimiza o cache para entidades que não são atualizadas.

  • NONSTRICT_READ_WRITE – Cache que é atualizado eventualmente.

  • READ_WRITE – Cache que possui atualização e leitura simultâneos e constantes.

Fazendo Caching das Queries

Para habilitar o caching das queries no seu código é bem simples. De posse do objeto Query, chame o seu método setCacheable(true).

É recomendável que se crie um método específico para este tipo de query assim como abaixo:

public List resultCachedList(String queryString, Object... params) {
Query query = ...
...
query.setCacheable(true);
query.list();

}

Conclusão

O Caching L2 (possibilitado pelo EhCache/Hibernate) se mostra uma solução muito eficaz em cases onde há muita busca em entidades que apresentam pouca ou nenhuma atualização. Aumenta consideravelmente o desempenho da aplicação, chegando em alguns casos a poupar até 20 segundos ao carregar a tela de uma funcinalidade.

Documentação

http://ehcache.org/documentation/hibernate.html

Tutoriais

http://www.devmedia.com.br/post-3881-Fazendo-cache-de-objetos-com-Hibernate-Parte-I.html

http://www.devmedia.com.br/post-3881-Fazendo-cache-de-objetos-com-Hibernate-Parte-I.html

http://blog.dynatrace.com/2009/02/16/understanding-caching-in-hibernate-part-one-the-session-cache/

http://blog.dynatrace.com/2009/02/16/understanding-caching-in-hibernate-part-two-the-query-cache/

http://blog.dynatrace.com/2009/03/24/understanding-caching-in-hibernate-part-three-the-second-level-cache/

Blogs Posts

http://www.javalobby.org/java/forums/t48846.html

Leitura Recomendada

http://ehcache.org/documentation/web_caching.html

Blog Logo

Allan Larangeiras


Publicado em

Image
Continuar lendo