Problemas para mapear n:n hibernate no EJB

10 respostas
mrb0305

Já fiz dessa maneira e funcionou mais não era no ejb
que poder me ajudar eu agradeço
abraços

Mensagem de erro:

14:00:07,565 INFO [STDOUT] 14:00:07,534 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: br.com.trackbus.entity.Grupo.permissoes, no session or session was closed

Mapemaneto na classe Grupo

@ManyToMany(mappedBy=grupos)

private List permissoes;
Mapeamento na classe permissão

@ManyToMany

@JoinTable(name=ADM_GRUPO_PERMISSAO,

joinColumns=@JoinColumn(name=PER_ID),

inverseJoinColumns=@JoinColumn(name=GRU_ID))

private List grupos;

10 Respostas

A

mas este ocorre au subir a aplicação ou ao invocar o método getAlgumaCoisa?

outra coisa, coloque seu sódigo entre [CODE]

dev.rafael

Preste muita atenção nessa classe LazyInitializationException pq vc vai ve-la bastante, ao menos enquanto vc ñ tiver muita XP com JPA.

O problema aqui é q todo relacionamento x:n é por padrão configurado como LAZY.
Relacionamentos podem ser LAZY ou EAGER. Os relacionamentos EAGER são carragados do banco no momento q a entidade q os possui é carregada. Enquanto os LAZY só são carregados quando vc tenta acessar esse relacionamento, o problema é q p/ fazer isso é necessário q haja uma transação aberta nesse momento, o q nem sempre é o caso.
Relacionamentos LAZY são, quase sempre, uma boa idéia pois eles reduzem a quantidade de memória necessária p/ manter as entidades e o tempo de carregamento delas. Mas infelismente eles só funcionam quando vc está dentro de uma transação. P/ resolver isso use JOIN FETCH nas queries quando vc souber q precisará acessar um relacionamento LAZY de fora da transação em q a entidade foi carregada.

select g from Grupo g join fetch g.permissoes

O JOIN FETCH força um relacionamento b]LAZY[/b] ser carregado como EAGER nessa query.

mrb0305

Ocorreu ao invocar o método no caso foi em tempo de execução
certo?

mrb0305

Oi dev.rafael
Só não entendi se devo criar um método para esse join.
obrigado

A

vc invocou o método numa jsp, controller, repositório, onde?

mrb0305

Ele é está em um Control do Jsf

A

Uma solução seria vc mudar o comportamento do relacionamento, como o dev.rafael postou, ManyToMany por padrão tem um comportamento Lazy, se vc mudar para Eager, vai funcionar, porém, toda vez que se carregar um “Grupo”, a query vai fazer um “join” com o “Permissoes”, vc querendo ou não querendo carregar as permissões.

Outra alternativa, seria aplicar o conceito de “openSessionInView” (google -> openSessionInView jsf bean ejb), mas como vc está num contexto EJB, não sei se tem como, pois o bean recebe “uma cópia” (serializada) do Grupo, e nesta “camada” já saiu do Contexto EJB (Alguêm com mais experiência em EJB me corrija se estiver errado, Obrigado).

Sugestão: faça um serviço que recebe o Grupo e retorna suas permissões, vc terá um pouco mais de código, mas vai funcionar, faça funcionar, depois busque uma alternativa, se tiver tempo.

Espero ter ajudado

mrb0305

Obrigado AAAquino essa solução funcionou

Mais me diz uma coisa isso não vai tornar algumas consultas minhas mais lentas?

Por exemplo quando eu quizer listar usuários do sistema ele vai carregar o grupo que ele pertence e suas permissões também?

abraços

A

Se existe uma associação do tipo

class Usuario

@ManyToOne // <- comportamento default é Eager)
List<Grupo> grupo

sim, irá fazer um join com as 3 tabelas toda vez que se carregar um usuário

mrb0305

Valeu AAAquino e dev.rafael pela força
abraços

Criado 4 de novembro de 2010
Ultima resposta 5 de nov. de 2010
Respostas 10
Participantes 3