Hibernate - Cache

Cache é um mecanismo para aprimorar o desempenho de um sistema. É uma memória intermediária que fica entre o aplicativo e o banco de dados. A memória cache armazena itens de dados usados ​​recentemente para reduzir o número de acessos ao banco de dados tanto quanto possível.

O cache também é importante para o Hibernate. Ele utiliza um esquema de cache multinível, conforme explicado abaixo -

Cache de primeiro nível

O cache de primeiro nível é o cache de sessão e é um cache obrigatório pelo qual todas as solicitações devem passar. O objeto Session mantém um objeto sob seu próprio poder antes de confirmá-lo no banco de dados.

Se você emitir várias atualizações para um objeto, o Hibernate tenta atrasar a atualização o máximo possível para reduzir o número de instruções SQL de atualização emitidas. Se você fechar a sessão, todos os objetos que estão sendo armazenados em cache serão perdidos e persistidos ou atualizados no banco de dados.

Cache de segundo nível

O cache de segundo nível é opcional e o cache de primeiro nível sempre será consultado antes que seja feita qualquer tentativa de localizar um objeto no cache de segundo nível. O cache de segundo nível pode ser configurado em uma base por classe e por coleção e principalmente responsável por objetos de cache em sessões.

Qualquer cache de terceiros pode ser usado com o Hibernate. Aorg.hibernate.cache.CacheProvider interface é fornecida, que deve ser implementada para fornecer ao Hibernate um identificador para a implementação do cache.

Cache em nível de consulta

O Hibernate também implementa um cache para conjuntos de resultados de consulta que se integra intimamente com o cache de segundo nível.

Este é um recurso opcional e requer duas regiões de cache físico adicionais que mantêm os resultados da consulta em cache e os carimbos de data / hora quando uma tabela foi atualizada pela última vez. Isso só é útil para consultas que são executadas com freqüência com os mesmos parâmetros.

O Cache de Segundo Nível

O Hibernate usa o cache de primeiro nível por padrão e você não precisa fazer nada para usar o cache de primeiro nível. Vamos direto para o cache de segundo nível opcional. Nem todas as classes se beneficiam do armazenamento em cache, por isso é importante poder desabilitar o cache de segundo nível.

O cache de segundo nível do Hibernate é configurado em duas etapas. Primeiro, você deve decidir qual estratégia de simultaneidade usar. Depois disso, você configura a expiração do cache e os atributos do cache físico usando o provedor de cache.

Estratégias de simultaneidade

Uma estratégia de simultaneidade é um mediador, que é responsável por armazenar itens de dados no cache e recuperá-los do cache. Se você for habilitar um cache de segundo nível, terá que decidir, para cada classe e coleção persistente, qual estratégia de simultaneidade de cache usar.

  • Transactional - Use esta estratégia para dados principalmente de leitura, onde é fundamental evitar dados obsoletos em transações simultâneas, no caso raro de uma atualização.

  • Read-write - Novamente, use essa estratégia para dados em sua maioria de leitura, onde é fundamental evitar dados obsoletos em transações simultâneas, no caso raro de uma atualização.

  • Nonstrict-read-write- Essa estratégia não garante a consistência entre o cache e o banco de dados. Use essa estratégia se os dados quase nunca mudam e uma pequena probabilidade de dados desatualizados não é uma preocupação crítica.

  • Read-only- Uma estratégia de simultaneidade adequada para dados, que nunca muda. Use-o apenas para dados de referência.

Se vamos usar o cache de segundo nível para nosso Employee , vamos adicionar o elemento de mapeamento necessário para dizer ao Hibernate para armazenar em cache as instâncias de Employee usando a estratégia de leitura e gravação.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <cache usage = "read-write"/>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

O atributo usage = "read-write" diz ao Hibernate para usar uma estratégia de simultaneidade de leitura e escrita para o cache definido.

Provedor de Cache

Sua próxima etapa após considerar as estratégias de simultaneidade, você usará suas classes candidatas de cache para escolher um provedor de cache. O Hibernate força você a escolher um único provedor de cache para toda a aplicação.

Sr. Não. Nome e descrição do cache
1

EHCache

Ele pode armazenar em cache na memória ou em disco e armazenamento em cluster e suporta o cache de resultado de consulta Hibernate opcional.

2

OSCache

Oferece suporte ao armazenamento em cache na memória e no disco em uma única JVM com um rico conjunto de políticas de expiração e suporte a cache de consulta.

3

warmCache

Um cache de cluster baseado em JGroups. Ele usa invalidação em cluster, mas não oferece suporte ao cache de consulta do Hibernate.

4

JBoss Cache

Um cache em cluster replicado totalmente transacional, também baseado na biblioteca multicast JGroups. Ele suporta replicação ou invalidação, comunicação síncrona ou assíncrona e bloqueio otimista e pessimista. O cache de consulta do Hibernate é compatível.

Cada provedor de cache não é compatível com todas as estratégias de simultaneidade. A matriz de compatibilidade a seguir o ajudará a escolher uma combinação apropriada.

Estratégia / Provedor Somente leitura Nonstrictread-write Ler escrever Transacional
EHCache X X X  
OSCache X X X  
SwarmCache X X    
JBoss Cache X     X

Você especificará um provedor de cache no arquivo de configuração hibernate.cfg.xml. Escolhemos EHCache como nosso provedor de cache de segundo nível -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>
   
      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         root123
      </property>
   
      <property name = "hibernate.cache.provider_class">
         org.hibernate.cache.EhCacheProvider
      </property>
   
      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>
   
   </session-factory>
</hibernate-configuration>

Agora, você precisa especificar as propriedades das regiões de cache. EHCache tem seu próprio arquivo de configuração,ehcache.xml, que deve estar no CLASSPATH do aplicativo. Uma configuração de cache em ehcache.xml para a classe Employee pode se parecer com isto -

<diskStore path="java.io.tmpdir"/>

<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>

<cache name = "Employee"
maxElementsInMemory = "500"
eternal = "true"
timeToIdleSeconds = "0"
timeToLiveSeconds = "0"
overflowToDisk = "false"
/>

É isso, agora temos o cache de segundo nível habilitado para a classe Employee e o Hibernate, agora atinge o cache de segundo nível sempre que você navegar para um Employee ou quando carregar um Employee por identificador.

Você deve analisar todas as suas classes e escolher a estratégia de cache apropriada para cada uma das classes. Às vezes, o cache de segundo nível pode reduzir o desempenho do aplicativo. Portanto, é recomendado fazer o benchmark de seu aplicativo primeiro, sem habilitar o cache e depois habilitar o cache adequado e verificar o desempenho. Se o armazenamento em cache não estiver melhorando o desempenho do sistema, não há por que habilitar qualquer tipo de armazenamento em cache.

O cache de nível de consulta

Para usar o cache de consulta, você deve primeiro ativá-lo usando o hibernate.cache.use_query_cache="true"propriedade no arquivo de configuração. Definindo esta propriedade como true, você faz o Hibernate criar os caches necessários na memória para manter os conjuntos de consulta e identificador.

Em seguida, para usar o cache de consulta, use o método setCacheable (Boolean) da classe Query. Por exemplo -

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

O Hibernate também oferece suporte a cache de baixa granularidade através do conceito de região de cache. Uma região de cache é parte do cache que recebe um nome.

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

Este código usa o método para dizer ao Hibernate para armazenar e procurar a consulta na área de funcionários do cache.