Obrigado por visitar a devmedia.com.br!

Precisamos de você para divulgar nossos vídeos e cursos gratuitos para a comunidade.

Se você gosta da devmedia.com.br por favor dê-nos o seu clique para o Google+ e ajude outros desenvolvedores ao redor do mundo.



Obrigado por seu apoio!
Equipe DevMedia

sair sem compartilhar (x)
DevMedia - asp.net, Java, Delphi, SQL e web Design, tudo em um só lugar!
Bem vindo a DevMedia!
LOGIN:     SENHA:

Fazendo cache de objetos com Hibernate - Parte II

Este artigo vai demonstrar como utilizar o Second Level Cache do Hibernate, que permite ter um maior controle sobre os objetos que estão em cache.

 

Este artigo vai demonstrar como utilizar o Second Level Cache do Hibernate, que permite ter um maior controle sobre os objetos que estão em cache.

EHCache

O EHCache é o framework default de cache do Hibernate. Para utilizá-lo basta colocar o ehcache.jar no classpath da aplicação. Para utilizar outro framework, como por exemplo o OSCache, é necessário alterar o arquivo hibernate.cfg.xml e incluir a seguinte linha:

 

<property name="hibernate.cache.provider_class">net.sf.hibernate.cache.OSCacheProvider </property>

 

Para este artigo, não é necessário alterar esta propriedade, pois vamos assumir o EHCacheProvider (default).

Ativando o cache para a classe Notícia

Para utilizar o cache, é necessário configurar o hibernate.conf.xml, conforme visualizado abaixo.

 

<mapping resource="model/Noticia.hbm.xml" />

     

<class-cache class="model.Noticia" usage="read-write" />

 

Neste exemplo vamos utilizar o tipo “read-write” o qual permite a leitura e gravação de novas informações. Outro tipo que pode ser utilizado é o “read-only” para as informações que não nunca serão atualizadas.

Secon Level Cache

Para configurar as propriedades do cache para a Notícia, é necessário adicionar o arquivo ehcache.xml no classpath da aplicação. Copie este arquivo da pasta de distribuição do Hibernate e insira as seguintes configurações:

 

<cache name="model.Noticia"

        maxElementsInMemory="100"

        eternal="false"

        timeToIdleSeconds="300"

        timeToLiveSeconds="600"

        overflowToDisk="false"

/>

 

Note que neste caso o nome do cache é o nome completo da classe “model.Noticia”. Caso o nome do cache não seja encontrado, o cache default será utilizado. Este cache também é configurado no arquivo ehcache.xml com a tag “<defaultCache>”.

 

Abaixo as explicações de cada propriedade que pode ser configurada:

 

Þ      maxElementsInMemory: número máximo de objetos que podem ficar armazenados em memória.

Þ      eternal: se configurado para “true”, significa que o cache nunca vai expirar.

Þ      timeToIdleSeconds: tempo em segundos que um objeto pode permanecer inutilizado no cache.

Þ      timeToLiveSeconds: tempo em segundos que um objeto pode ficar em cache.

Þ      overflowToDisk: se configurado para “true” e caso o limite de objetos em memória seja superior ao definido pela propriedade “maxElementsInMemory”, as informações serão armazenadas em disco.

 

Pronto, isto é tudo. Agora os objetos “Notícia” serão armazenados em cache.

Testando o cache

Para testar o cache, vamos fazer o mesmo exemplo que foi utilizado no artigo anterior. Inicialmente é feita uma consulta no banco de dados com a primeira Session. Logo depois a tabela Notícia é atualizada utilizando JDBC. Então a Session atual é fechada, e uma nova é aberta. Através do Second Level Cache, a segunda Session consegue recuperar os objetos em cache, respeitando as configurações de limite de objetos em memória e tempo de expiração definidos no arquivo ehcache.xml.

 

//1ª consulta…

 

//JDBC com update…

 

//fecha a 1ª session (fecha conexão e elimina o first level cache)

t.commit();

session.close();

 

//cria uma nova session

session = sessionFactory.openSession();

t = session.beginTransaction();

 

//2ª consulta…

//As informações retornadas aqui estão em cache

 

Faça o teste, e você verá que o resultado retornado pela 2ª consulta é o mesmo retornado pela 1ª, uma vez que o cache é utilizado, e não é feita uma consulta no banco de dados.

Cache para a Query

A classe Query é frequentemente utilizada para realizar consultas no banco de dados utilizando HQL, como por exemplo:

 

Noticia n = (Noticia) session.createQuery("from Noticia where id = 1").setCacheable(true).uniqueResult();

 

Note que para utilizar o cache da Query, o método setCacheable(true) foi chamado para informar o Hibernate que é necessário fazer cache da consulta.

 

Porém para o cache funcionar, é necessário adicionar a seguinte linha no arquivo hibernate.cfg.xml:

 

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

 

Por default, o nome do cache (conhecido como região) utilizado é “org.hibernate.cache.StandardQueryCache”. Portanto, do mesmo modo que anteriormente foi configurado o cache para a classe Notícia, é necessário configurar as propriedades do cache para a Query, conforme visualizado abaixo:

 

<cache name="org.hibernate.cache.StandardQueryCache"

        …… outras propriedades aqui

/>

 

Caso seja necessário customizar o cache a ser utilizado por cada consulta, pode-se utilizar o método “setCacheRegion” da classe Query:

 

Noticia n = (Noticia) session.createQuery("from Noticia where id = 1").setCacheable(true).setCacheRegion("cacheNoticia").uniqueResult();

 

Desta forma uma configuração de cache precisa ser criada para o nome “cacheNoticia”, conforme demonstrado abaixo:

 

<cache name="consultaNoticia"

       …… outras propriedades aqui

/>

Log4j

O log4j pode ser utilizado para debugar a execução do cache. Para ativar os logs, insira a seguinte linha no arquivo log4j.properties:

 

log4j.logger.org.hibernate.cache=debug,stdout

 

Para demonstrar os logs, execute o código abaixo:

 

public class TesteCache3 {

      public static void main(String[] args) throws Exception {

            SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

            Session session = sessionFactory.openSession();

            Transaction t = session.beginTransaction();

 

            //Recupera a notícia do banco.

            System.out.println("1 - pre session.get");

            Noticia n = (Noticia) session.createQuery("from Noticia where id = 1").setCacheable(true).setCacheRegion("consultaNoticia").uniqueResult();

            System.out.println("1 - pos session.get");

            System.out.println(n.getTitulo());

           

//          Fecha a 1ª session

            t.commit();

            session.close();

 

            //    Atualiza a tabela usando JDBC.

            Class.forName("org.hsqldb.jdbcDriver");

            Connection conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/hello","sa","");

            Statement stmt = conn.createStatement();

            stmt.executeUpdate("update noticia set titulo = 'novo titulo'");

           

            session = sessionFactory.openSession();

            t = session.beginTransaction();

 

//Faz a busca na 2ª session e utiliza o cache “consultaNoticia”

            System.out.println("2 - pre session.get");

            n = (Noticia) session.createQuery("from Noticia where id = 1").setCacheable(true).setCacheRegion("consultaNoticia").uniqueResult();

            System.out.println("2 - pos session.get");

            System.out.println(n.getTitulo());

 

            t.commit();

            session.close();

      }

}

 

A saída do programa pode ser visualizada abaixo:

 

DEBUG CacheFactory:39 - instantiating cache region: model.Noticia usage strategy: read-write

 INFO UpdateTimestampsCache:43 - starting update timestamps cache at region: org.hibernate.cache.UpdateTimestampsCache

 WARN EhCacheProvider:103 - Could not find configuration [org.hibernate.cache.UpdateTimestampsCache]; using defaults.

DEBUG EhCacheProvider:106 - started EHCache region: org.hibernate.cache.UpdateTimestampsCache

 INFO StandardQueryCache:51 - starting query cache at region: org.hibernate.cache.StandardQueryCache

1 - pre session.get

 INFO StandardQueryCache:51 - starting query cache at region: consultaNoticia

 WARN EhCacheProvider:103 - Could not find configuration [consultaNoticia]; using defaults.

DEBUG EhCacheProvider:106 - started EHCache region: consultaNoticia

DEBUG StandardQueryCache:93 - checking cached query results in region: consultaNoticia

DEBUG EhCache:104 - key: sql: select noticia0_.ID as ID0_, noticia0_.titulo as titulo0_, noticia0_.texto as texto0_ from Noticia noticia0_ where noticia0_.ID=1; parameters: ; named parameters: {}

DEBUG EhCache:113 - Element for sql: select noticia0_.ID as ID0_, noticia0_.titulo as titulo0_, noticia0_.texto as texto0_ from Noticia noticia0_ where noticia0_.ID=1; parameters: ; named parameters: {} is null

DEBUG StandardQueryCache:98 - query results were not found in cache

Hibernate: select noticia0_.ID as ID0_, noticia0_.titulo as titulo0_, noticia0_.texto as texto0_ from Noticia noticia0_ where noticia0_.ID=1

DEBUG ReadWriteCache:148 - Caching: model.Noticia#1

DEBUG EhCache:104 - key: model.Noticia#1

DEBUG EhCache:113 - Element for model.Noticia#1 is null

DEBUG ReadWriteCache:160 - Cached: model.Noticia#1

DEBUG StandardQueryCache:67 - caching query results in region: consultaNoticia

1 - pos session.get

Titulo antigo

2 - pre session.get

DEBUG StandardQueryCache:93 - checking cached query results in region: consultaNoticia

DEBUG EhCache:104 - key: sql: select noticia0_.ID as ID0_, noticia0_.titulo as titulo0_, noticia0_.texto as texto0_ from Noticia noticia0_ where noticia0_.ID=1; parameters: ; named parameters: {}

DEBUG StandardQueryCache:147 - Checking query spaces for up-to-dateness: [Noticia]

DEBUG EhCache:104 - key: Noticia

DEBUG EhCache:113 - Element for Noticia is null

DEBUG StandardQueryCache:108 - returning cached query results

DEBUG ReadWriteCache:75 - Cache lookup: model.Noticia#1

DEBUG EhCache:104 - key: model.Noticia#1

DEBUG ReadWriteCache:85 - Cache hit: model.Noticia#1

2 - pos session.get

Titulo antigo

Conclusão

Neste artigo foi explicado como configurar o Second Level Cache do Hibernate, e como demonstrado é uma tarefa relativamente simples.

 

Fazer cache de objetos pode aumentar a performance de sua aplicação, mas cuidado para não abusar muito, porque isto pode aumentar consideravelmente a quantidade de memória que sua aplicação está utilizando.

 

A configuração ideal para cada aplicação, cabe a você descobrir. Até a próxima.





    0 COMENTÁRIO

[Fechar]

Este post é fechado - você precisa ter acesso ao post para incluir um comentário.


Nenhum comentário foi postado - seja o primeiro a comentar!



Autor
Ricardo Rodrigues Lecheta

Ricardo Rodrigues Lecheta (ricardolecheta@terra.com.br), é autor do livro “Google Android” - Aprenda a criar aplicações para dispositivos móveis utilizando o Android SDK e possui as certificações SCJP, SCWCD, SCBCD, SCMAD, SCEA.


Space do autor
Estatísticas
Favorito:
Comentários:
Feedback:
Utilidade:
2   1
[Fechar]

Você precisa estar logado para dar um feedback.

Clique aqui para efetuar o login
[Fechar]
Este post está disponível para assinantes da Java Magazine ou para quem possui Créditos DevMedia.

  Conheça os planos de créditos DevMedia e visualize esse post agora mesmo!

Plano conveniência – Neste plano este post custa R$ 0,00 (Compre agora)
Esse plano permite que você compre somente um post, pagando por ele seu preço sem desconto.

Plano ocasional: Aqui este post custa: R$ -1,00 (assinante) ou R$ -1,00 (não-assinante)
Este plano é ideal para quem tem interesse em mais de um post. Você compra um mínimo de R$ 50,00 em créditos e ganha, em média, 50% de desconto no preço do post. Compre Créditos agora!

Assinatura de Créditos (Plano econômico) – Aqui este post custa R$ -1,00
Este plano é ideal para quem tem interesse em muitos posts. Com esse plano você compra R$ 180,00 em créditos e ganha, em média, 80% de desconto no preço do post. Assine este plano agora!

> Saiba mais sobre o Sistema de Créditos DevMedia
web-03
DevMedia  |  Anuncie  |  Fale conosco
Hospedagem web por Porta 80 Web Hosting
2012 - Todos os Direitos Reservados a web-03