2
respostas

Boas práticas com o Lazy Loading

Boa tarde.

Tentarei não alongar mas preciso contextualizar minha situação e entender o que ocorre.

Entrei recentemente em uma empresa onde já havia um projeto iniciado utilizando Hibernate, tenho trabalho há algum tempo e vinha notando que o fetch = FetchType.LAZY, não era respeitado, exceto quando combinado com optional = false.

Comecei a desenvolver um processo no sistema que gravava por volta de 200 registros, mas notei uma certa lentidão, como sempre notei no restante do sistema e outros processos.

Ativei o log de queries para dar uma olhada e reparei que para cada Item, eram feitas 40 consultas, lotadas de inners e left joins, apesar dos mesmos estarem Lazy.

Então pesquisando na internet encontrei sobre a propriedade:

<property name="hibernate.enable_lazy_load_no_trans" value="true"/>

Verifiquei e no projeto que eu estou trabalhando, o antigo desenvolvedor setou está propriedade.

Fiz o teste retirando a mesma e várias telas pararam de funcionar por conta das relações que não eram mais carregadas por padrão, até ai normal. Fiz o teste fazendo o JOIN FETCH do que precisava e funcionou normalmente, diminuindo drasticamente o número de queries.

A pergunta é, qual seria a boa prática para essa questão? Vejo que o enable_lazy_load_no_trans ele remove o funcionamento do Lazy, gostaria de confirmar isso é realmente uma péssima prática?

Mesmo retirando esta propriedade, os @OneToOne continuam carregando por default, mesmo com Lazy. Há alguma maneira de evitar isso? Vi algo sobre PersistentAttributeInterceptable, seria o caminho?

Obrigado desde já.

2 respostas

Olha, acho que você tem um belo de um problema. Não conhecia essa propriedade e ela realmente parece ser meio demoníaca. https://vladmihalcea.com/the-hibernate-enable_lazy_load_no_trans-anti-pattern/

O cara que mantém esse blog que eu citei, é uma das referências em Hibernate e Banco de dados no mundo de desenvolvimento Java.

O seu colega colocou essa propriedade porque ele tomava lazyinitialization e talvez tenha decidido não usar o open session in view ou até nem conhecia. Só que ele é ainda pior, pq para cada elemento ele abre uma nova conexão... No lazyload normal, a mesma conexão seria usada.

Se você colocar o Open Session in view, mesmo sendo considerado anti pattern por alguns, já deve dar uma melhorada. E aí você tenta remover a propriedade mesmo...

Boa noite Alberto, muito obrigado pela atenção.

Então foi nessa conclusão que cheguei mesmo, também cheguei até o blog do Vlad Mihalcea e percebi que se trata de uma péssima solução.

Sei que sua resposta será um pouco óbvia, mas o mais correto mesmo, seria retirar a propriedade e acertar o sistema utilizando Lazy com JOIN FETCH em todos os lugares, certo?

Desculpa usar a oportunidade para perguntar também, eu justamente cheguei até essa propriedade, pois tive de fazer um processo que grava um Item e suas Composicoes (Matérias-Primas e etc) e também faz um acumulado e grava em outras duas entidades.

Por mais que seja uma quantidade considerável de registros, por volta de 200 e pouco, achei muito lento.

Qual seria a abordagem para este caso? Você recomenda usar técnicas de batch ou outra coisa? Esses 200 e poucos registros eram para ser lentos?

Muito obrigado novamente pela atenção, se puder tirar essas dúvidas. Ficarei muito grato.