Hibernate Objetos de cache do 2º nível que são preguiçosos = false, resultam em uma busca padrão = junção, está documentado em qualquer lugar?
-
21-09-2019 - |
Pergunta
Eu experimento a seguinte questão aparentemente indocumentada e quero entender se
- eu fiz algo errado
- Alguém encontrou o mesmo problema?
- Realmente não está documentado em nenhum lugar? Ou eu perdi alguma coisa?
O comportamento é que isso assuma o seguinte mapeamento
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Primeiro, como pano de fundo, o valor padrão de hiberna para o buscar atributo em uma relação muitos para um deve ser "Selecione", Isso é pelo menos o que está documentado (vou adicionar o link aqui quando o encontrar)
No entanto, isso aparentemente é verdade apenas se a classe referenciada for preguiçosa = "verdadeiro"!
Então, aparentemente, o mapeamento acima é traduzido para isso (porque a barra é preguiçosa = "falsa"):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Agora, por que isso seria um problema? Em vez de 2 seleciona, o Hibernate carregará a referência não preguiçosa em uma única seleção com seu "pai" (carregue foo com barra em uma única seleção)
Isso realmente faz sentido, já que o objeto não é preguiçoso, por que não carregá -lo?
A resposta é a seguinte: o que acontece se a barra estiver no cache do 2º nível?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
E a resposta para isso é - nada muda!
Aparentemente, seria de assumir que o Hibernate é inteligente o suficiente para entender que os objetos desse tipo não devem ser carregados, mas como a busca padrão foi alterada de seleção para ingressar, o Hibernate não tem escolha (você não pode se juntar a uma tabela real com o 2º cache de nível ainda)
Portanto, o Hibernate faz o que é dito e usa uma junção para buscar um objeto no banco de dados onde ele já está no 2º cache de nível
A solução que encontrei é literalmente mudar o mapeamento para buscar = "selecionar"
Agora, quando a segunda seleção para bar está prestes a ir, o Hibernate entende que não deve ir ao banco de dados e buscá -lo no cache. e apenas 1 consulta será executada (após o aquecimento)
Solução
Encontrei o mesmo problema e me vi marcando todas as relações muitos para um que serão armazenados em cache como fetch="select"
. No momento em que a consulta é construída, o Hibernate não pode saber se a instância solicitada da barra está no cache de segundo nível ou não (supondo que o foo não esteja em cache).