Boas práticas com o Lazy Loading

9 respostas
jsfjavaormhibernate
A

Boa tarde.

Peguei um projeto já 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á.

9 Respostas

J

Perfeito, é isso que você deve fazer mesmo se usar Hibernate. Deixa o lazy só no mapeamento mas faz o fetch nas queries.

Lazy é um recurso inútil para aplicações web. O ideal seria não usar Hibernate, que possui excesso de engenharia para atender os resultados.

A

O ideal seria não usar Hibernate, que possui excesso de engenharia para atender os resultados.

Você diz trabalhar com native queries?

J

Sim, é mais eficiente e fica sob controle do profissional. Dá uma pesquisada sobre JDBCTemplate, é um meio termo entre JDBC puro com ORM, mas totalmente baseado em query SQL e sem as gorduras do hibernate, que não fazem mais sentido para aplicações atuais.

A

Certo, vou dar uma olhada no JDBCTemplate.

Apenas para concluir, essa decisão da utilização de JDBCTemplate não depende exclusivamente de mim, se tiver de optar por continuar com o Hibernate. A melhor estratégia seria utilizar tudo Lazy e sempre trabalhar com os join fetchs a nível de query, correto?

J

Exato, HQL com join fetch é a forma mais profissional de trabalhar com Hibernate, gerando dentro do possível uma única query para o resultado. Nunca fique gerando queries através do acesso aos atributos de forma preguiçosa, literalmente.

A

Entendi, perfeito.

Obrigado pelas dicas, vou dar uma olhada no JDBCTemplate, acredito que trabalhar com ambos no mesmo projeto não tenha problema.

J

Com Hibernate você também pode trabalhar com SQL, mas mesmo assim ainda existe o consumo da fábrica de sessões do Hibernate. Enfim, basta trabalhar com HQL para sair do caos.

A

Seria essa a ideia né:

List<Object[]> acumuladosMps = getEntityManager().createNativeQuery("SELECT * FROM acumulados_materias_primas WHERE id = :id AND acumulado_data = :acumulado_data")
            .setParameter("id", item.getId())
            .setParameter("acumulado_data", new Date())
            .getResultList();

Por exemplo esta mesma consulta feita com NamedQuery chega a dar uma travada quando faço o debug.

Seria essa a opção?

J

Com SQL sim e também pode mapear para uma entidade. Mas como está adotando Hibernate, o normal é usar HQL, e SQL para queries complexas, principalmente relatórios.

Prefiro SQL sem Hibernate, mas trabalhar com Hibernate 100% via SQL está carregando uma mochila com chumbo para não usar, meio que perde o sentido.

Criado 13 de abril de 2018
Ultima resposta 13 de abr. de 2018
Respostas 9
Participantes 2