Fórum JPA Lazy Load too lazy! #400333

05/05/2011

0

Galera estou desenvolvendo uma aplicação JPA + JSF, baseado nos cursos do Dyego Carmo, e me deparei com um problema, que ao meu ver é um BUG, no lazy load do JPA. Muito, muito estranho!
Para adiantar o problema é o seguinte:Fiz um método no DAO para carregar uma propriedade lazy da entidade.Quando rodo um teste de unidade onde é necessário carregar essa propriedade, o JPA acusa:failed to lazily initialize a collection of role: br.com.myfinances.entity.Parcela.lancamentoList, no session or session was closedPorém quando boto pra DEPURAR o teste, advinhem só! Ele carrega!! :-O Funciona sem erro nenhum!
Vou postar abaixo as partes necessárias do código...(Para contextualizar vocês, trata-se de uma aplicação financeira)
Tenho uma classe Conta que possui uma propriedade lancamentoList no modo lazy:
    @OneToMany(mappedBy = "conta")    private List<Lancamento> lancamentoList;

Tenho um ContaDAO, onde botei um método para carregar essa propriedade dentro duma sessão aberta:
    public List<Lancamento> loadLancamento(Conta conta) {        EntityManager em = JPAUtil.getInstance().getEntityManager();        conta = em.getReference(Conta.class, conta.getIdConta());        List<Lancamento> toReturn = conta.getLancamentoList();        em.close();        return toReturn;    }

(lembrando que o método JPAUtil.getInstance().getEntityManager() retorna um EM com transação aberta)
Daí no teste de unidade tenho a seguinte chamada:
        //-- Recuperando LANÇAMENTO a partir da Conta        List<Lancamento> lancamentoList = contaDAO.loadLancamento(conta);        Lancamento lancamento = lancamentoList.get(0); 

E quando executo o teste..... PAU!Ele acusa o erro mostrado no início, dizendo que não foi possível carregar a propriedade.
Mas daí eu fui debugar para ver porque estava ocorrendo esse maldito erro.Então lá vou eu, de F8 em F8, executando passo-a-passo esse método. De repente, terminei a depuração e o teste foi executado com sucesso!
Náaa, não é possível!!! Executei mais 20 vezes para acreditar que isso estava ocorrendo e está!Inclusive na própria depuração se eu mandar executar de vez ele acusa o erro.Só funciona quando eu vou passo-a-passo no método, devagarzinho.Pois é, esse Lazy Mode do JPA está muuuito lazy! (Ô meu rei... Ó paí ó!) 
Já tentei algumas maneiras para tentar dar uma "freada" no método mas sem sucesso.
O que vocês sugerem?Já viram isso?
Abraços.
att.Jovan Andrade
Jovan Junior

Jovan Junior

Responder

Posts

05/05/2011

Jovan Junior

Resolvi o problema ajustando o modo de recuperação do objeto no DAO. Troquei de getReference(...) para find(...).
Para visualizar:
    public List<Lancamento> loadLancamento(Conta conta) {        EntityManager em = JPAUtil.getInstance().getEntityManager();        //conta = em.getReference(Conta.class, conta.getIdConta());        conta = em.find(Conta.class, conta.getIdConta());        List<Lancamento> toReturn = conta.getLancamentoList();        em.close();        return toReturn;    }


Mesmo assim, continuo intrigado com isso. Mesmo usando o getReference(...) não deveria dar erro. (Ao meu ver)O JPA teria que esperar o objeto carregar para depois partir para a próxima execução. Por que ele não faz isso?
Será que o JPA está sendo burro ao ponto de fazer duas cargas nesse caso (1º carregar o objeto sem a propriedade, 2º carregar a propriedade)?
Na minha cabeça, ao usar o getReference(...), eu estaria poupando uma ida a mais no banco desnecessária.No caso ele deveria, trazer o objeto completo, já com a propriedade, pois solicitei a propriedade diretamente.(Se ainda não carregou o objeto, carregue com tudo que precisa ora!)
Alguém pode me desmistificar esse caso com certeza?
att.Jovan Andrade
Responder

Gostei + 0

05/05/2011

Davi Costa

Usando Hibernate?

veja esse link:

https://www.devmedia.com.br/forum/viewtopic.asp?id=393925

Att Davi
Responder

Gostei + 0

05/05/2011

Davi Costa

Responder

Gostei + 0

10/05/2011

Dyego Carmo

Uma coisa que tenho observado é que o EclipseLINK funciona melhor que o Hibernate em casos de controlar os exceptions lazy...

em todo caso,

Resolvido ? Favor fechar :)
Responder

Gostei + 0

10/05/2011

Jovan Junior

Resolver, resolvi, como postei acima.
Porém não me foi explicado por que quando uso o getReference() não funciona mas quando uso o getEntity() funciona.
Sendo que o que acontece com o getReference() não é que não funciona, mas na verdade é "lerdeza" ou preguiça para retornar a lista solicitada.Pois quando solicito a lista rodando a aplicação normalmente dá o erro de LazyException, mas quando rodo no modo debug, que dou um tempo para receber a lista, ela vem e não ocorre erro nenhum, funciona perfeitamente.
Responder

Gostei + 0

10/05/2011

Jovan Junior

corrigindo o que escrevi acima, não é getEntity mas find, como vocês podem ver no código.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar