[Resolvido] LazyInitializationException. Como ler atributos (listas) de objeto sem usar EAGER?

Estou utilizando classes do controlador JPA geradas pelo Netbeans, para fazer CRUD de objetos do banco de dados para uma aplicação desktop.

Tenho um objeto da classe Curso que tem uma lista de objetos da classe Disciplina assim:

@ManyToMany(fetch=FetchType.EAGER)
private List<Disciplina> disciplinas;

Precisei colocar como EAGER pois sem ele não conseguia editar o objeto no bando de dados. Sempre obtinha uma LazyInitializationException (Sim, eu sei, a seção foi fechada e não consigo ler os atributos do objeto. É o que acontece normalmente no Hibernate) quando alterava a lista de disciplinas e mandava o controladolador JPA editar o objeto da classe curso:

Dentro da classe Disciplina tenho uma lista de outras disciplinas que são pré-requisitos para esta.

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) protected List<Disciplina> prerequisitos;

Mas quando tenho mais de um EAGER, em classes diferentes é lançada essa exceção:

Procurei por tudo e não encontrei solução.

Como eu resolvo isso? Estou em cima do prazo e preciso de uma solução rápida. Por favor me ajudem!

Para resolver rápido… faça uma outra query para puxar a lista… e associe os objetos…

Primeiro de tudo, obrigado por sua atenção! Já antecipo o agradecimento a qualquer outro que venha me ajudar também.

Segundo, eu sou meio noob então por favor não se estresse com as perguntas cretinas! Como assim outra query? Pode explicar melhor? Onde e como eu faço isso?

Tipo, eu estou utilizando controller.findCursoEntities(); para carregar os objetos do banco de dados, sendo que controller é um objeto de uma classe do controlador JPA, e poderia utilizar também controller.findCurso(id);.

Fera, dá uma olhada nesse link!
http://www.javalobby.org/java/forums/t20533.html
Vais entender bem o lance do lazy.

Procure pelo método initialize(), você carrega as coleções com ele, de acordo com a tua demanda.

Abraço!

oi

ja usei dessa forma em um projeto e funcionou, porem eu usava Set e não List:

@OneToMany (fetch= FetchType.EAGER, mappedBy="teste") @Fetch(FetchMode.SELECT) private Set<Teste> testeSet;

não sei se interfere em alguma coisa, mas vc pode tentar…

da uma olhada nesse link: http://community.jboss.org/thread/107685?tstart=0
tem uma parte que o cara fala: “Acho que a resposta é a mesma para todos nós - não use List, a menos que você tenha uma razão muito boa. Use Set.”

Espero ter ajudado
abraço

Hibernate.initialize(curso);

[quote=drsmachado] Hibernate.initialize(curso); [/quote]

Não entendi bem em que ponto devo usar isso. É quando carrego os cursos da base de dados? Antes de atualizá-los na base? Tenho que usar isso nas coleções do curso também?
Tentei usar da seguinte maneira:

private List<Curso> carregaCursos() { List<Curso> cursos = controller.findCursoEntities(); Hibernate.initialize(cursos); return cursos; }
Mas continuei com LazyInitializationException.

Quando você recupera o objeto ao qual estas listas está associado.
Por exemplo, se Cursos possui uma List listaDisciplina, use-o no objeto de Cursos.

Tentei modificar o código acima assim:

[code] private List getTableLines() {
List cursos = controller.findCursoEntities();
for (int i = 0; i < cursos.size(); i++) {
Hibernate.initialize(cursos.get(i));

    }
    return cursos
}[/code]Mas continua dando a exceção. A exceção que surge é:[code]Exception in thread "AWT-EventQueue-0" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: univ.model.Curso.disciplinas, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:249)
    e assim vai...[/code]

E ocorre nesse ponto:

public List<Disciplina> getSearchMatches() { List tempLines = new ArrayList(); for (Disciplina line : (tableLines = getTableLines())) { <============ O ERRO OCORRE AQUI if (searchMatches(line)) { tempLines.add(line); } } return tempLines; }

Sendo que getTableLines() retorna a lista de disciplinas do objeto curso que eu já tinha posto em uma variável global.

Você não pode me indicar algum pequeno tutorial sobre o assunto?

Para usar o initialize… é necessário que a sessão ainda esteja aberta…

Tipo… acho que vc está mexendo com coisas muito avançadas para seu conhecimento… sugiro estudar… banco de dados… SQL… JDBC e só depois hibernate…

Agora é tarde demais, não vai dar tempo.

Tentei modificar o método da classe do controlador JPA para que aplicasse o initialize com a seção ainda aberta.

private List<Curso> findCursoEntities(boolean all, int maxResults, int firstResult) { EntityManager em = getEntityManager(); try { Query q = em.createQuery("select object(o) from Curso as o"); if (!all) { q.setMaxResults(maxResults); q.setFirstResult(firstResult); } List<Curso> list = q.getResultList(); for (int i = 0; i < list.size(); i++) { Hibernate.initialize(list.get(i)); } return list; } finally { em.close(); } }

Mas o erro persiste.

O problema é que isso não acontece quando crio um novo objeto no banco de dados. É quando vou editar que ocorre a exceção.

Você tem que dar initialize é na coleção que quer carregar… e não no curso…

Hibernate.initialize(curso.getMinhaColecao());

Gente, muito obrigado! Era isso mesmo. Alterei o seguinte método dentro da classe do controlador JPA e funcionou:

private List<Curso> findCursoEntities(boolean all, int maxResults, int firstResult) { EntityManager em = getEntityManager(); try { Query q = em.createQuery("select object(o) from Curso as o"); if (!all) { q.setMaxResults(maxResults); q.setFirstResult(firstResult); } List<Curso> list = q.getResultList(); for (int i = 0; i < list.size(); i++) { Hibernate.initialize(list.get(i).getCadeiras()); } return list; } finally { em.close(); } }

1 curtida