Problemas com lazy em relacionamento manyToMany

Boa tarde,
pessoal tenho duas classes “Aluno, Modalidade” e dentro de aluno tenho uma lista de modalidades!
mapeie da seguinte maneira:

@ManyToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.LAZY)
	@JoinTable(
		name="TB_ALUNO_MODALIDADE", 
		joinColumns={@JoinColumn(name="AL_ID")},
		inverseJoinColumns={@JoinColumn(name="MD_ID")}
	)
	private List<Modalidade> listModalidade;

ao cadastrar um novo aluno tudo funciona perfeitamente, mas ao editar, na hora de carregar a pagina de edição
de um aluno que tenha modalidades cadastradas para ele ocorre o erro de lazy:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: 
br.com.fitness.beans.Aluno.listModalidade, no session or session was closed

se eu mudar o fetch=FetchType.LAZY para fetch=FetchType.EAGER
funciona! mas eu utilizo essa classe em outros lugares, entao não seria interessante pra mim
carregar essa lista toda vez!
alguem sabe oque pode estar erra e consequentemente causando esse erro?
vlw

Meu amigo,

eu tive o mesmo problema que você e não o solucionei. A explicação que chegamos na época era que a sessão hibernate usada no momento em que os objetos eram carregados do banco durante o deploy da aplicação era uma e que as sessões que depois tentavam acessá-los eram outras, e, portanto, dava esse problema.

Nós resolvemos manter o EAGER onde era aceitável e, onde não era produtivo, usávamos HQLs para carregar os objetos, usando o ‘fetch’:

HQL = "FROM Aluno a LEFT JOIN FETCH a.modalidades"

Com isso, os mapeamentos LAZY são recuperados. Obviamente, é uma solução ruim e tenho certeza de que há melhores. Acompanharei esse tópico em busca dessas formas mais adequadas.

Abraços,

Rodrigo.

vlw rodrigo!!
interessante oque vcs fizeram, mas acredito que seja apenas alguma configuração no controle da sessão
e acho que a solução possa ser mais simples do que imaginamos!!
utilizando somente JPA isso não ocorre!
se alguem souber de mais uma dica fica avontade para posta-las vlw

Concordo com você, tem que haver uma solução decente, e aguardo que os colegas nos ajudem! :slight_smile:

Se estiver trabalhando com Criteria, pode usar esse método

/** * Specify an association fetching strategy for an association or a * collection of values. * * @param associationPath a dot seperated property path * @param mode The fetch mode for the referenced association * @return this (for method chaining) */ public Criteria setFetchMode(String associationPath, FetchMode mode) throws HibernateException;

E definir essa associção, somente para essa consulta, como FetchMode.JOIN (equivalente ao EAGER)

eai fabio blz?!!
Cara não da pra mim fazer isso pq acontece o seguinte:
eu tenho uma página de listagem de alunos cadastrados no sistema e um link editar para cada linha

<h:commandLink value="editar" action="alunoForm" id="editarLink" styleClass="styleLink" immediate="true"> <f:setPropertyActionListener value="#{objeto}" target="#{mb_alunoForm.aluno}"/> </h:commandLink>
note que eu utilizo o setPropertyActionListener e seto o objeto da lista detro do objeto do meu formulario para edição!
portanto eu não realizo busca desse objeto pq pego ele da lista! e esse objeto aluno tem uma lista de modalidades que esta com lazy.

E vc não pode fazer isso antes? Na consulta da tela já preparar esse dados com o Criteria?

se eu fizer isso fabio, seria um peso desnecessário para minha aplicação!
por exemplo:
na listagem eu não preciso da lista de modalidades então pq eu iria busca-la? entendeu
se fosse assim eu colocaria fatchType.EAGER que funcionaria perfeitamente! já testei isso
mas não quero que essa lista venha carregada msm…

Ok, entendi. Bom, não sei o que vc está usando, mas então nesse momento de edição vc vai precisar
chamar algum código que faça isso, que vai até lá o banco e acorde as associações usadas.

é verdade!
tipo eu poderia muito bem criar um método editar e antes de encaminhar para a pagina de edição eu realizava a busca para tirar o lazy
mais ai eu teria que utilizar a sessão para encaminhar o objeto para outra pagina e eu não quero utilizar sessão!
to lendo no site da jboss uma solução curiosa para isso!!!
tipo se eu criar um método de edição eu não preciso fazer busca! não explicitamente…
basta eu acessar a lista desse objeto tipo aluno.getListModalidade().size(); no momento que eu der o size na lista
ele ativa os objetos dela!!
vou testar isso se der certo eu posto

Eu tinha lido uma dica assim, mas, no meu caso, obtinha um belo nullpointer exception.

Pessoal! pra quem estiver acompanhando o tópico!!
consegui resolver o problema!! mas mesmo assim não gostei da minha solução que isso fique bem claro!
criei um método editar no meu managed bean da pagina de listagem

public String editarAction() { HibernateUtil.currentSession().refresh(aluno); sessionScope.setAttribute("aluno", aluno); return "alunoForm"; }
e o jsp ficou assim:

<h:commandLink value="editar" [b]action="#{mb_alunoList.editarAction}"[/b] id="editarLink" styleClass="styleLink" immediate="true"> <f:setPropertyActionListener value="#{objeto}" target="#{mb_alunoList.aluno}"/> </h:commandLink>

notem que chamei um método editar e neste método eu faço o

HibernateUtil.currentSession().refresh(aluno); onde este é a solução do problema…
e depois adiciono meu objeto na sessão e encaminho para outra página…

por enquanto vou deixar assim, mas vou ver se consigo identificar outra forma de solucionar este problema…
se alguem tiver mais alguma idéia ai fiquem avontade!! vlw