Could not initialize proxy - no Session

9 respostas
adrianostanley
Tenho os seguintes mapeamentos e recebo um org.hibernate.LazyInitializationException: could not initialize proxy - no Session.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="br.com.bolao.beans.BeanTeam" table="team">
		<id name="id" column="idteam" type="java.lang.Integer">
			<generator class="increment" />
		</id>
		<property name="name" type="java.lang.String" />
	</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="br.com.bolao.beans.BeanGame" table="game">
		<id name="id" column="idgame" type="java.lang.Integer">
			<generator class="increment" />
		</id>
		<property name="homeTeamScore" type="java.lang.Integer" />
		<property name="visitorTeamScore" type="java.lang.Integer" />
		<many-to-one name="homeTeam" class="br.com.bolao.beans.BeanTeam"
			column="id_hometeam" cascade="all" foreign-key="id_hometeam" />
		<many-to-one name="visitorTeam" class="br.com.bolao.beans.BeanTeam"
			column="id_visitorteam" cascade="all" foreign-key="id_hometeam" />			
		<property name="gameDay" type="java.util.Date" />	
	</class>
	
	<class name="br.com.bolao.beans.BeanTeam">
		<id name="id" column="idteam" type="java.lang.Integer">
			<generator class="increment" />
		</id>
	</class>
</hibernate-mapping>
Alguém poderia me indicar o que há de errado com esses mapeamentos??

9 Respostas

nbluis

Não é problema nos mapeamentos…
O problema é que o(s) objeto(s) relacionados ao objeto que está trabalhando (os tais many-to-one) são LAZY, ou seja, só serão carregados quando chamados.

Porém você deve estar transitando seu objeto para fora do container (o contexto persistente), assim perdendo a conexão com o banco para buscar os dados lazy.

Dai ao tentar utilizar qualquer dado/objeto lazy ele dá esse erro pois não é possível carregar os dados requeridos…

Solução.

  1. Utilize Eager (bad)
  2. Inicialize os dados que irás utilizar fora do container antes de sair dele.
    Como? Faça chamadas aos atributos…
    tipo
beanGame.getHomeTeam.getDadoqueserausado().toString();
adrianostanley

Opa, então, nem citei acima, mas pra salvar tá funcionando legal… ele grava os registros normalmente…
É só pra listá-los que está dando isso…
Resumi as ações da busca num método só pra ficar mais fácil mostrar aqui:

public List<E> list() throws Exception{ SessionFactory factory = new Configuration().addClass(clazz).buildSessionFactory(); Session session = factory.openSession(); Query q = session.createQuery("from BeanGame bg"); List<E> list = q.list(); session.flush(); session.close(); factory.close(); return list; }
Como ficaria aqui por exemplo pra inicializar os dados antes de retorná-los, como proposto na reposta acima??
Desde já muito obrigado!!
Adriano

nbluis

Ummm… seu problema é mais simples…

A questão é que vc está fechando a session após consultar.
Porém, existe algum dado da lista que ainda não foi carregado…

Por exemplo:

Você tem uma lista de BeanGame, e cada BeanGame tem um BeanTeam.
Seu BeanTeam é lazy inicialization dentro do BeanGame.

Quanto você fizer algo como.

for (BeanGame b : list) {
  int i = v.getBeanTeam().getPropriedade();
}

se o BeanTeam é lazy, no momento da chamada ele vai tentar ir no banco pra carregar os dados do BeanTeam.

Porém como sua sessão foi fechada
[/code]session.close();[/code]
ele não consegue carregar e estoura esta excessão.

Para resolver, ou você torna seu atributo EAGER (fetch=“join”, veja mais) ou você faz uma chamada ao atributo antes de fechar a sessão.
Ex.

public List<E> list() throws Exception{  
  SessionFactory factory = new Configuration().addClass(clazz).buildSessionFactory();  
  Session session = factory.openSession();  
  Query q = session.createQuery("from BeanGame bg");  
  List<BeanGame> list = (List<BeanGame>)q.list();  
  
  for (BeanGame b : list) {
    b.getBeanTeam().getPropriedade();
  }
  session.flush();  
  session.close();  
  factory.close();  
  return list;  
}

Dai ele vai ser carregado antes de fechar a sessão…

Até.

adrianostanley

Então cara… pelo que li faz sentido e entendi a possível causa.
Mas chamei as duas propriedades que são mapeadas como many to one e continuou dando exatamente o mesmo erro.

public class TestBeanDAOList{ public static void main(String[] args){ BeanDAO&lt;BeanGame&gt; btdao = new BeanDAO&lt;BeanGame&gt;(BeanGame.class); List&lt;BeanGame&gt; bt = null; try{ bt = btdao.list(); } catch(Exception e){ // TODO Auto-generated catch block e.printStackTrace(); } for(BeanGame beanTeam : bt){ System.out.println(beanTeam); //A EXCEÇÃO É DISPARADA AQUI. } } }
A exceção é disparada no momento que o objeto é usado pela primeira vez.
Achei estranho, não deveria gerar um NullPointerException?

nbluis
for(BeanGame beanTeam : bt){
			System.out.println(beanTeam); //A EXCEÇÃO É DISPARADA AQUI.
		}
	}

Isso precisa ser feito antes de fechar a sessão…

adrianostanley

Vou colocar aqui também os scripts de criação das duas tabelas…
Às vezes é aí que está o erro…

CREATE TABLE `team` ( `idteam` int(11) NOT NULL auto_increment, `name` varchar(55) NOT NULL, PRIMARY KEY (`idteam`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `game` ( `idgame` int(11) NOT NULL auto_increment, `id_hometeam` int(11) NOT NULL default '-1', `hometeamscore` int(2) default '-1', `id_visitorteam` int(11) NOT NULL default '-1', `visitorteamscore` int(2) default '-1', `gameday` date default NULL, PRIMARY KEY (`idgame`), KEY `id_hometeam` (`id_hometeam`), KEY `id_visitorteam` (`id_visitorteam`), CONSTRAINT `game_ibfk_1` FOREIGN KEY (`id_hometeam`) REFERENCES `team` (`idteam`), CONSTRAINT `game_ibfk_2` FOREIGN KEY (`id_visitorteam`) REFERENCES `team` (`idteam`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Muito obrigado pela paciência… :slight_smile:

nbluis

Isso precisa ser feito antes de fechar a sessão…
Chame algum método do beanname…

for(BeanGame beanTeam : bt){
			beanTeam.getName().toString();
		}
	}

assim…

adrianostanley

Então, hehe, a exceção agora já não é mais no proxy, session, etc…
Gera uma NullPointer… debuguei e vi que os objetos de BeanTeam estão nulos no BeanGame.
Pelo menos não é o mesmo erro. :slight_smile:
Muito obrigado pela ajuda!!

aureliolima

tb tava tendo o mesmo erro que vc…

mas no meu caso era pra acessar um atributo de uma classe herdada, porém resolvi o problema apenas setando o lazy=true, no mapeamento da classe herdada.

Criado 7 de janeiro de 2008
Ultima resposta 13 de ago. de 2010
Respostas 9
Participantes 3