JPA/Hibernate ...melhor pratica de uso LAZY ou EAGER

Olá,

uma duvida qual FetchType usar LAZY ou EAGER pois vejo alguns exemplo
na internet onde qdo tem uma lista se usar EAGER isso é uma regra ???

abs


@OneToMany(fetch = FetchType.LAZY, mappedBy = "par")
private List<Tabela> children = new ArrayList<Tabela>();

principalmente com listas que acho q não é bom usar EAGER… imagina c tu tem a seguinte cadeia…

PAIS que tem uma lista de ESTADOS que tem uma lista de CIDADES …

ai tu pega um pais BRASIL … se tiver egaer… ele vai carregar direto do banco, 27 estados… e de quebra ~5600 municipios…

ai agora tu imagina que tu tenha EMPRESA, que tenha uma lista de funcionarios…

ai quando tu busca um empresa… tu vai catar por tabela … 5000 funcionarios, que vai ter pendurado por exemplo 5 paises… com uns 100 estados e umas 10000 cidades

tem motivo ? pra isso ser EAGER ??

com LAZY… quando vc cata um PAIS… so vem ele… c vc kizer a lista de stados… getEstados() e pronto… la vem os estados… c pracisar ai tu pega a lista de cidades de um único estado por exemplo… não precisa puxar 5600 municipios só pq catou o brasil…

mesma coisa pra empresa… as vezes vc ker referenciar a empresa… não tem pra q… via EAGER vc puxa os 5000 funcionarios… c precisar vc pega a lista de funcionarios…

Pra lista, principalmente sou a favor do LAZY

Pra lista nao se discute LAZY de certeza,

agora temos que analisar pra objetos @ManyToOne

Por ex:

se eu tiver um objeto que tenha Empresa, que tem Usuario, que tem Pais, que tem Estado, que tem Cidade

se eu utilziar EAGER (default)

qndo eu solicitar Empresa, ele ira buscar todos os objetos ligados

ja o LAZY buscaria so o Empresa, e quando eu precisasse Usuario por exemplo eu faria um empresa.getUsuario.getId() e ai sim faria a busca

porem temos um problema nas arquiteturas View x Core (com sessoes nao ligadas),

qndo o objeto esta na view, a sessao com hibernate esta fechada, nao possibilitando fazer este recurso de empresa.getUsuario.getId(),

ocasionando um erro na view de no proxy… nao sei oq, não me lembro agora.

De qualquer forma, seria interessante eu poder escolher o nivel de eager, por exemplo, carregar so no primeiro nivel

empresa carregaria somente usuario, sem carregar o resto, porem nao sei se é possivel fazer isto? alguem sabe?

Deixem de besteira! Não existe essa de LAZY é melhor que EAGER se for lista!

Você usa um ou outro dependendo do contexto. Exemplo: imagine que você precisa exibir determinado carro e todos os acessórios opcionais instalados (num mapeamento, um Carro tem como propriedade Set). Se as duas entidades serão exibidas numa única tela, é recomendável usar EAGER, para usar apenas uma única consulta SQL. Usar LAZY implica em (n + 1) consultas e isso não é “performático” (apesar dessa palavra ridícula).

Se não fosse isso, ou seja, a tela de acessórios opcionais estivesse numa tela diferente (através de um link na página). Aí o melhor seria usar LAZY, pois o usuário poderia nunca clicar nos links e trazer os registros juntos (com EAGER) seria desperdício.

Concordo totalmente com o Leonardo3001 isso depende muito do que vai ser aplicado. Pois se usar lazy onde há necessidade é um eager vai ficar muito lento e vice-versa. Onde necessite de um select simples lazy é a melhor solução. Agora se precisar de joins o melhor é eager.

abs,

[quote=Leonardo3001]Deixem de besteira! Não existe essa de LAZY é melhor que EAGER se for lista!

Você usa um ou outro dependendo do contexto. Exemplo: imagine que você precisa exibir determinado carro e todos os acessórios opcionais instalados (num mapeamento, um Carro tem como propriedade Set). Se as duas entidades serão exibidas numa única tela, é recomendável usar EAGER, para usar apenas uma única consulta SQL. Usar LAZY implica em (n + 1) consultas e isso não é “performático” (apesar dessa palavra ridícula).

Se não fosse isso, ou seja, a tela de acessórios opcionais estivesse numa tela diferente (através de um link na página). Aí o melhor seria usar LAZY, pois o usuário poderia nunca clicar nos links e trazer os registros juntos (com EAGER) seria desperdício.

[/quote]

voce pode usar LAZY e fazer uma pesquisa “performatica” hehehe,

usando “from Carro as c left outer join fetch c.opcionais where c.id = :id” por ex.

resultaria em 1 busca

creio que quando se fala em perfomence no hibernate tem que cuidar MUITO no uso do eager.

Ninguem respondeu a pergunta na minha resposta anterior,
alguem ja usou EAGER em objeto @ManyToOne e conseguiu limitar o nivel de consultas?

no caso de Empresa -> Usuario -> Cidade

carregar so empresa e usuario, tendo como todos @ManyToOne o default (Eager)?

paribe,

Só pra ajudar no esclarecimento, LAZY quer dizer algo como “preguiçoso”, ou seja, qdo for buscar um Estado no BD por exemplo, vc teria apenas o contexto de Estado na sessão.
Exemplo:

class Estado {

   @OneToMany(fetch=FetchType.LAZY)
   private Set<Cidade> cidades;

   public Set<Cidade> getCidades {
      return cidades;
   }
}

Qdo vc for chamar:

public void incluiCidade (Estado estado, Cidade cidade) {
   estado = estadoDao().getPeloId(estado.getId); // Performance. Se o atributo Set<Cidade> estiver como LAZY, o objeto Estado não vai carregar os dados das Cidades neste chamada. Não tem necessidade!
   try {   
       estado.adicionarCidade(cidade); // aqui ele apenas adiciona a cidade
   } catch (AlgumaCoisaException e) {
      system.out.print(e.getMessage());
   }
}

Já o EAGER, vem de “ligeiro”, e carrega os dados junto com o objeto requisitado.
Agora vamos supor que no seu sistema, cada Estado tem um PerfilEstado. Um PerfilEstado é uma classe que tem posicaoGeografica, entre outros atributos de um Perfil de um Estado.
Neste caso, segundo os requisitos do sistema, qdo se for trabalhar com um Estado,é interessante sempre ter os dados de perfil dele prontos, pois os dados estratégicos estão no perfil:

class Estado {
   
   //...cidades;

   @OneToOne(fetch=FetchType.EAGER)
   private PerfilEstado perfil;

   public PerfilEstado getPerfil {
      return perfil;
   }
}
estado = estadoDao().getPeloId(estado.getId()); // neste momento os dados do Perfil são carregados junto com os dados do estado

estado.getPerfil().setPontosTuristicos(String [] pontos); // Performance! como os dados do perfil já foram carregados outrora, agora esta chamada não terá que buscar nada no banco
double posicaoGeografica = estado.getPerfil().getPosicaoGeografica(); // Performance novamente

Concorda que se PerfilUsuario fosse LAZY, a cada chamada (uso do Perifl) do getPerfil(), teria um trabalho de carregar os dados no banco?
Aí é que está a diferença entre LAZY e EAGER. Não tem melhor nem pior. Oq existe é necessidade de performance.

Espero ter ajudado.

[code] estado = estadoDao().getPeloId(estado.getId()); // neste momento os dados do Perfil são carregados junto com os dados do estado

estado.getPerfil().setPontosTuristicos(String [] pontos); // Performance! como os dados do perfil já foram carregados outrora, agora esta chamada não terá que buscar nada no banco
double posicaoGeografica = estado.getPerfil().getPosicaoGeografica(); // Performance novamente [/code]

neste caso se fosse LAZY, para realizar uma busca só, vc poderia fazer um HQL, usando o FETCH.

Ex.: “from Estado left outer join fetch estado.perfil”, o retorno seria os estados com o perfil carregado, mesmo a anotação estando em LAZY.

Outra situacao,

por exemplo, se necessitar algum objeto que tenha “estado”, se estiver com eager em perfil, trará perfil, sem ter necessidade.

Por isso, considero o LAZY uma melhor opção para quem quer performance, consequentemente terá um pouco mais de trabalho no desenvolvimento.

e EAGER para quem quer pouco trabalho no desenvolvimento, porém terá uma menor performance.

[]'s

Realmente. Toda vez que for caregar o estado, o perfil será carregado junto. Este é o “contra” no EAGER. E dá menos trabalho no desenvolvimento.