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.