Tenho dificuldade em entender quando o Hibernate atinge o cache de segundo nível e quando invalida o cache.
Isso é o que eu entendo atualmente:
- O cache de segundo nível armazena entidades entre sessões, o escopo é a SessionFactory
- Você tem que dizer quais entidades armazenar em cache, nenhuma entidade será armazenada em cache por padrão
- O cache de consulta armazena resultados de consultas no cache.
O que não entendo é
- Quando a hibernação atinge esse cache?
- Digamos que eu configurei o cache de segundo nível, mas não o cache de consulta. Eu quero armazenar meus clientes em cache, há 50000 deles. De que forma posso recuperar os clientes do cache?
- Presumo que posso obtê-los por id no cache. Isso seria fácil, mas também não vale a pena armazenar em cache. Mas e se eu quiser fazer alguns cálculos com todos os meus clientes. Digamos que eu queira mostrar uma lista dos clientes, então como posso acessá-los?
- Como obteria todos os meus clientes se o cache de consultas estivesse desabilitado?
- O que aconteceria se alguém atualizasse um dos clientes?
- Esse cliente seria invalidado no cache ou todos os clientes seriam invalidados?
Ou estou pensando que o cache é totalmente errado? Quais seriam os usos mais apropriados do cache de segundo nível nesse caso? A documentação do hibernate não deixa claro como o cache funciona na realidade. Existem apenas instruções sobre como configurá-lo.
Update: Então, eu entendi que o cache de segundo nível (sem cache de consulta) seria bom para carregar dados por id's. Por exemplo, tenho um objeto de usuário que desejo verificar se há permissões em cada solicitação em um aplicativo da web. Seria um bom caso para reduzir o acesso ao banco de dados, armazenando o usuário no cache de segundo nível? Como se eu armazenasse a id do usuário na sessão ou onde quer que eu precisasse verificar as permissões, carregaria o usuário por sua id e verificaria as permissões.
Respostas:
Em primeiro lugar, vamos falar sobre cache de nível de processo (ou cache de segundo nível, como o chamam no Hibernate). Para fazer funcionar, você deve
Você diz ao provedor de cache quantos objetos ele deve armazenar e quando / por que eles devem ser invalidados. Então, digamos que você tenha entidades Book e Author, cada vez que você as obtém do DB, apenas aquelas que não estão no cache serão selecionadas do DB. Isso aumenta o desempenho significativamente. É útil quando:
Então, quando o cache funciona?
session.get()
ousession.load()
o objeto que foi selecionado anteriormente e reside no cache. Cache é um armazenamento em que ID é a chave e as propriedades são os valores. Portanto, somente quando houver a possibilidade de pesquisar por ID você poderá eliminar o acerto no DB.Mas não funciona quando:
from Authors where name = :name
então você não acessa o cache.where id = ?
).fetch="join"
, isso significa que, para carregar associações, as junções serão usadas em todos os lugares em vez de instruções select separadas. O cache de nível de processo funciona em objetos filhos apenas sefetch="select"
for usado.fetch="select"
mas em HQL, você usa junções para selecionar associações - essas junções serão emitidas imediatamente e sobrescreverão tudo o que você especificou em hbm.xml ou anotações.Agora, sobre Query Cache. Você deve notar que não é um cache separado, é uma adição ao cache de nível de processo. Digamos que você tenha uma entidade País. É estático, então você sabe que sempre haverá o mesmo conjunto de resultados quando você disser
from Country
. Este é um candidato perfeito para cache de consulta, ele armazenará uma lista de IDs em si mesmo e quando você selecionar todos os países da próxima vez, ele retornará essa lista para o cache de nível de processo e este, por sua vez, retornará objetos para cada ID pois esses objetos já estão armazenados no cache de segundo nível. O cache de consulta é invalidado cada vez que algo relacionado à entidade muda. Digamos que você tenha configuradofrom Authors
para ser colocado em um Cache de Consulta. Não será eficaz porque o autor muda frequentemente.fonte
Na realidade, é útil ter um cache distribuído de valor-chave - isso é o memcached, e ele alimenta o Facebook, Twitter e muitos mais. Mas se você não tiver pesquisas por id, não será muito útil.
fonte
Atrasado para a festa, mas queria responder sistematicamente a essas perguntas que muitos desenvolvedores fazem.
Tomando sua pergunta uma por uma aqui está minha resposta.
A. O cache de primeiro nível está associado ao objeto de sessão . O segundo nível de cache está associado ao objeto Session Factory . Se o objeto não for encontrado no primeiro, o segundo nível será verificado.
A. Você teve essa resposta em sua atualização. Além disso, o cache de consulta armazena apenas a lista de IDs do objeto e os objetos escritos em seus IDs são armazenados no mesmo cache de segundo nível. Portanto, se você habilitar o cache de consulta, utilizará o mesmo recurso. Legal, certo?
A. Respondido acima.
A. Respondido acima.
R. O Hibernate não tem ideia, mas você pode usar outros caches de IMDG / distribuídos de terceiros para serem implementados como cache de segundo nível de hibernação e invalidá-los. por exemplo, TayzGrid é um desses produtos e acho que há mais.
fonte
O cache de segundo nível do Hibernate é um pouco complicado de entender e implementar. Aqui está o que podemos dizer com base em suas perguntas:
Como você sugere, o cache L2 do Hibernate (se habilitado; não é ativado por padrão) é consultado somente após o cache L1. Este é um cache de valor-chave cujos dados são preservados em várias sessões.
O cache de consulta seria o melhor para este caso de uso, uma vez que os dados do cliente são estáticos e recuperados de um banco de dados relacional.
Depende da estratégia específica de cache do Hibernate que você está usando. O Hibernate, na verdade, tem quatro estratégias de cache diferentes:
SOMENTE LEITURA : Objetos não mudam uma vez dentro do cache.
NONSTRICT_READ_WRITE : Objetos mudam (eventualmente) após a entrada do banco de dados correspondente ser atualizada; isso garante consistência eventual.
LER ESCREVER : Objetos mudam (imediatamente) após a entrada do banco de dados correspondente ser atualizada; isso garante consistência forte usando bloqueios "suaves".
TRANSACIONAL : Objetos mudam usando transações XA distribuídas, garantindo a integridade dos dados; isso garante sucesso total ou reversão de todas as alterações. Em todos esses quatro casos, no entanto, atualizar uma única entrada do banco de dados não invalidaria toda a lista de clientes no cache. O Hibernate é um pouco mais inteligente do que isso :)
Para aprender mais sobre como o cache L2 funciona no Hibernate, você pode verificar o artigo “O que é o cache L2 do Hibernate,” ou o artigo detalhado Cache no Hibernate com Redis
fonte