LazyInitializationException em ManyToOne mesmo com FetchType == JOIN (left outer join)

5 respostas
C

olá
sei q LazyInitializationException eh comum por ai mas pesquisei muuuito antes de postar aqui
eu tenho o seguintes beans (vou resumir o codigo)
estah dando lazy no manytoone Empresa e seu manyToone TipoEmpresa

colaborador->empresa->tipoempresa

public class Colaborador implements Serializable {
	private Long id;
	private PessoaFisica pessoaFisica;
	private Empresa empresa;
	private Colaborador superiorImediato;

...
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "EMPRESA_ID")
	public Empresa getEmpresa() {
		return this.empresa;
	}...

empresa->tipoempresa

public class Empresa implements Serializable {
	private Long id;
	private TipoEmpresa tipoEmpresa;
...
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "TIPO_EMPRESA_ID")
	public TipoEmpresa getTipoEmpresa() {
		return this.tipoEmpresa;
	}...

tipoempresa

public class TipoEmpresa implements Serializable {
	private Long id;
	private String tipoEmpresa;

o erro acontece quando eu vou fazer uma busca por TODOS os colaboradores

antes de tudo considere que no banco de dados , a tabela Empresa possui soh um registro, e nesse unico registro nao foi informado o TipoEmpresa, isto eh. Empresa.tipoEmpresa eh NULL

como eu busco TODAS AS COLUNAS dos colaboradores e preciso de alguns dados como pessoaFisica.nome, empresa.nomeFantasia e etc, dai eu ajusto o fetch mode join nas propriedades pessoaFisica ,empresa e superiorImediato do bean Colaborador… ateh ai beleza… eu consigo obter os dados normalmente… (ateh aqui, eu ainda nao recebi o Lazy pq empresa.tipoEmpresa eh null, nao salvei ainda um TipoEmpresa para a empresa)

MAS, se atualizar o unico registro da tabela de empresa e ajustar o TipoEmpresa neste registro, isto é, Empresa.tipoEmpresa for igual a 1 por exemplo (1 eh a FK da tabela TipoEmpresa) eu obtenho o LazyInitalizationException…

eu mando o hibernate fazer join soh em pessoaFisica ,empresa e superiorImediato, esperando q empresa.tipoEmpresa venha apenas um objeto TipoEmpresa com o ID 1 e mais nenhum dado… isto eh quero soh o id de tipoEmpresa(fk salva no banco)… (diferente se fosse EAGER, onde empresa.tipoEmpresa viria o objeto completo, com id e todos os outros dados)
mas continuo recebendo o lazy

alguem pode me ajudar com este problema?
eu NAO quero TipoEmpresa na consulta de todos os colaboradores , apenas a empresa.nomeFantasia q eles correspondem
detalhe: se eu acessar o criteria.list() logo dps de executar a sql, o objeto TipoEmpresa de Empresa jah vai estar com Javassist_LazyInitializationException, isto eh, nao eh nada na view tentando acessar algo com a sessao fechada

sql gerada pelo hibernate

select
        this_.ID as ID5_3_,
        this_.EMPRESA_ID as EMPRESA2_5_3_,
        this_.PESSOA_FISICA_ID as PESSOA3_5_3_,
        this_.SUPERIOR_IMEDIATO_ID as SUPERIOR4_5_3_,
        empresa2_.ID as ID6_0_,
        empresa2_.CEI as CEI6_0_,
        empresa2_.CNPJ as CNPJ6_0_,
        empresa2_.CONTATO_ID as CONTATO23_6_0_,
        empresa2_.IMAGEM as IMAGEM6_0_,
        empresa2_.INSCRICAO_ESTADUAL as INSCRICAO14_6_0_,
        empresa2_.INSCRICAO_MUNICIPAL as INSCRICAO15_6_0_,
        empresa2_.LOGOMARCA as LOGOMARCA6_0_,
        empresa2_.NOME_FANTASIA as NOME18_6_0_,
        empresa2_.RAZAO_SOCIAL as RAZAO19_6_0_,
        empresa2_.RESPONSAVEL_ID as RESPONS24_6_0_,
        empresa2_.STATUS as STATUS6_0_,
        empresa2_.TELEFONE as TELEFONE6_0_,
        empresa2_.TIPO_EMPRESA_ID as TIPO25_6_0_,
        pessoafisi3_.ID as ID7_1_,
        pessoafisi3_.CPF as CPF7_1_,
        pessoafisi3_.NOME_COMPLETO as NOME3_7_1_,
        pessoafisi3_.RG as RG7_1_,
        colaborado4_.ID as ID5_2_,
        colaborado4_.EMPRESA_ID as EMPRESA2_5_2_,
        colaborado4_.PESSOA_FISICA_ID as PESSOA3_5_2_,
        colaborado4_.SUPERIOR_IMEDIATO_ID as SUPERIOR4_5_2_ 
    from
        colaborador this_ 
    left outer join
        empresa empresa2_ 
            on this_.EMPRESA_ID=empresa2_.ID 
    left outer join
        pessoa_fisica pessoafisi3_ 
            on this_.PESSOA_FISICA_ID=pessoafisi3_.ID 
    left outer join
        colaborador colaborado4_ 
            on this_.SUPERIOR_IMEDIATO_ID=colaborado4_.ID 
    where
        (
            1=1
        ) 
    order by
        this_.ID desc

5 Respostas

vitenho

manda a jpql query

C

achei a resposta
eh q minha interface grafica eh em Flex com BlazeDS
quando o BlazeDS acha um Javassist Lazy Initializer no objeto q veio de uma consulta do hibernate, ele lanca a excecao de qqr jeito, mesmo se eu nao acessar a propriedade
o desserializador dele acessa todas as propriedades
agora como eu vou resolver isso ainda nao sei, vi um pessoal q mexeu no core do hibernate, outro com outra solucao q engole a exception e etc
mas enquanto nao sei oq vou fazer vou deixando ele lancar a exception e monitorando a propriedade lazy q a lancou
pra galera q mexe com flex… alguma sugestao? (ai jah seria otro topico ne heheh)
valew

vitenho

cara uma coisa eh lazy exception e vc resolve com um servlet filter

outra é transient entity passed to persist

C

eu nao curto muito usar opensessioninview
acho meio gambiarra
qd quero as associassoes manytoone e onetomany sempre uso o Fetch ou dou get na colecao no momento certo
fiz um generic dao preparado pra isso tb

e no meu caso nao tem nada a ver com transient pra persistente
eh direto no resultado do list() do hibernate
qd suas entidades sao lazy os objetos sao inicializados com javassist lazy initializer
debuga ai pra vc ver

LeandroRSilva

Olá…
Estive procurando na net e cheguei nesse post que é bem semelhante ao meu problema… também estou trabalhando com Flex e BlazeDS e, relacionado ao assunto está acontecendo algo curioso… vamos lá:

tenho as classes: Servico, Pessoa, Permissao… em Permissao existe, entre outros, dois atributos: Servico servico; Pessoa pessoa…

todos anotados com @ManyToOne(fetch=FetchType.LAZY)

quando executo qualquer dos dois NamedQuery’s abaixo:

@NamedQuery(name="Permissao.getPessoasPermitidas",
            query="SELECT pp FROM Permissao p JOIN p.pessoa pp WHERE p.servico = :servico order by pp.nome")                
            
    ,
    
    @NamedQuery(name="Permissao.getPessoasPermitidas1",
            query="SELECT p.pessoa FROM Permissao p WHERE p.servico = :servico order by p.pessoa")

obtenho uma Collection normalmente… até ai tudo bem… retorno para o flex… fecho o EntityManager no final da Listener da requisição e beleza…

preencho uma DataGrid de boa…

A questão é… nesse ponto tem uma pessoa logada… para essa pessoa logar foi executado

public Pessoa login(String senha, String login) {

...
      Pessoa pessoa = findByLogin(login);
...

return pessoa;

}

Até ai beleza também…

Saca só… na listagem que sitei acima a lista vem corretissima e todos os objetos sao carregados mesmo o atributo pessoa sendo Lazy…

O problema é: se tenho uma lista por exemplo de 100 pessoas e uma dessas pessoas é aquela que foi dada um find antes, ou seja, a que esta logada… a lista vem certinha com 100 objetos, porém 99 carregados e aquele que foi dado um find(id) antes…

vem com javassist lazy initializer… ai já viu né… no DataGrid… tudo certo… e uma linha lá escrito [object object]…

Alguem sabe como resolver deixando o atributo pessoa e servico como lazy… pois segundo minha logica de teste de permissoes esse objetos só deveram realmente ser criados quando o administrador estiver dando ou negando permissoes… no dia a dia nunca é carregado pois para saber se um usuário tem permissao para determinado servico eu executo

@NamedQuery(name="Permissao.getForPessoaServico",
            query="SELECT p FROM Permissao p WHERE p.servico = :servico and p.pessoa = :pessoa")

se esse select é nulo significa que a pessoa logada não tem permissão… Porém… na manutenção dá o problema citado…


Curiozidade: Porque só o objeto que já foi dado um find(id) nele antes é que aparece na List, antes mesmo de ir para o Flex, como sendo da classe Pessoa_$$_javassist_0 e todos os outros que o Hibernate ainda não haviam sido carregados em outro momento, vem certo, ou seja, da classe Pessoa

Obrigado pessoal… essa é minha primeira iteração ativa apesar de ser leitor já ha algum tempo.

Criado 4 de junho de 2010
Ultima resposta 17 de set. de 2010
Respostas 5
Participantes 3