Spring - org.hibernate.LazyInitializationException/no session or session

25 respostas
T

Saudações,

Estou com um problema no Spring em ambiente Web, quando tento usar FetchType.LAZY.

Tenho duas classes:

Pessoa.java
@Entity
@Table(name = "TBPESSOAS")
public class Pessoa implements Serializable {

	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID_PESSOA")
	private Integer id;
	@Column(name = "DS_NOME")
	private String nome;
	@OneToMany(mappedBy = "pessoa", fetch = FetchType.LAZY)
	private List<Email> emails;
//gets sets
Email.java
@Entity
@Table(name="TBEMAILS")
public class Email implements Serializable {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID_EMAIL")
	private Integer id;
	@Column(name = "DS_EMAIL")
	private String email;
	@ManyToOne
	@JoinColumn(name = "ID_PESSOA", referencedColumnName = "ID_PESSOA")
	private Pessoa pessoa;
//gets sets
Em algumas pesquisas no Google, muitos dizem para usar o filter do hibernate que jah vem no Spring. web.xml
<filter>
		<filter-name>hibernateFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
		<init-param>
			<param-name>sessionFactoryBeanName</param-name>
			<param-value>sessionFactory</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>hibernateFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

Mas mesmo assim eu tenho a execessão.

Alguém sabe alguma solução para esse problema ?

25 Respostas

A

eu não usaria esse onetomany eu sempre não mapeio onetomany e crio metodos auxiliares nos DAO’s para filtrar ao maximo possivel e sempre retornar quando realmente eu quero e nunca tive problemas!

T

Ok.

Mas, pesquisando na Internet, soube que existe esse padrão, OpenSessionInView implementado no Spring. Deveria funcionar.

Poderia até fazer como voce falou, mas minha dúvida é que deveria funcionar esse filtro no Spring.

Obrigado.

A

sim eu implementei o OSV em meu projeto web também e acabou o problema
coloque essa linha na configuração do HibernateUtil

configuration.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");

e um filtro simples mapeado no xml

public class HibernateSessionRequestFilter implements Filter {

  
    public void init(FilterConfig config) throws ServletException{}

  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HibernateUtil.beginTransaction();
        try {
            response.setContentType("text/html; charset=UTF-8");
            chain.doFilter(request, response);
            HibernateUtil.commitTransaction();
        } catch (HibernateException exception) {
            exception.printStackTrace();
            HibernateUtil.rollbackTransaction();
        } finally {
            HibernateUtil.closeSession();
        }
    }

  
    public void destroy(){}

}
T

Só que eu não estou usando o HibernateUtil. Estou usando Spring.

Tem alguma diferença ?

A

eu não uso o spring! usando o spring vc vai ter que usar o filter dele creio eu! caso não consiga não use o spring! por qual motivo vc esta usando ele?

T

Uso ele para IOC. Estou utilizando o Flex, e na arquitetura que foi definida o Spring é utilizado.
O problema é que eu já utilizaei o filter do OpenSession do Spring, mas não fucionou.

T

Já encontrei vários artigos em Blogs e até mesmo aqui no Fórum do Guj, mas nada resolveu.

N

essa execção ele lança em que momento?

T

A excessão é lançada quando se usa o getEmails() da Classe Pessoa. Que está anotado com FetchType.LAZY.

@OneToMany(mappedBy = "pessoa", fetch = FetchType.LAZY) private List<Email> emails;

A

mas acontece esse erro mas a aplicação continua funcionando normalmente correto? a unica coisa que acontece é sair textos no log do servidor certo?

ou trava tudo?

T

Não tava. Somente lança a exceção, não trava.

N

Essa exeção é lançada justamente por causa do mapeamento lazy.

Quando vc faz um pessoa.getEmails() com esse mapeamento Lazy lança execão porque o lazy não carrega os emails automaticamente.

Ou vc muda o mapeamento para

@OneToMany(mappedBy = "pessoa", fetch = FetchType.EAGER) private List<Email> emails; Isso faz as coisas ficarem mais lentas…

ou você seta a lista de emails antes de utilizar o getemails tipo pessoa.setEmails(facade.buscaEmailsByPessoa(codPessoa))

uma sugestão… :slight_smile:

T

Ok, entendi.

Mas se o hibernate tem essa estratégia de Lazy, quer dizer que deveria funcionar. O que eu estou querendo é utilizar o Spring+Hibernate de forma correta.

Mas obrigado pela sugestão.

T

Ninguém tem nenhum idéia de como corrigir isso ?

T

Ainda não consegui resolver o problema. :?

C

Boa noite.

Não sei se o problema já foi resolvido, mas segue a seguinte sugestão:
http://developers-blog.org/blog/default/2010/02/17/Spring-Hibernate-LazyInitializationException

Espero ter ajudado.

T+

M

Olá Turim, Já se passou um bom tempo.
Estou com um problema igual ao seu,

Ja conseguiu usar da forma correta o Lazy.
Meu problema e ManyToMany que também não estou sabendo resolver.

Tenho Pepeis e regras

Quero pegar as regras de um papel!
mais uma condição só as regras ativas, mas tá dificil.

Se você puder me dar uma dicas!
Também gostaria de fazer do jeito certo mas to me quebrando.

Um abraço!

T

turim estou passando pelo mesmo problema… você conseguiu resolver o problema?

Desde já agradeço :smiley:

T

Também estou enfrentando esse problema.

Levei muito tempo pesquisando e encontrei algumas soluções embora não tenha conseguido implementa-las .Interceptor e o Filter que muitos sugerem.

Alguém poderia me ajudar a implementar a classe OpenSessionInViewInterceptor oferecida pelo Spring?

Em meu Controller eu preciso recuperar um dado do banco e utiliza-lo em uma classe de negócio, e quando eu tento utiliza-lo acontece a exceção LazyInitializationException, pois eu já havia fechado a sessão no método de busca.

Alguém têm algum código como exemplo que já implementou essa solução ou algum link para eu ler e entender o funcionamento desse interceptor, sei que ele funciona através de aspecto e posso manipular um metodo para acontecer antes, depois ou quando o metodo foi concluido, mas eu não sei como vou criar o
ApplicationContext context = new ClassPathXmlApplicationContext("/config/spring-persistence.xml");
utilizando esse interceptor, muito menos como vou passar a session para minhas classes DAO utilizarem para realizar suas operações.

Uso Spring 3 e Hibernate 4.

edit:
Depois de uma incrível batalha de 1 dia tentando encontrar essa bendita solução, finalmente consegui.

Não pude utilizar a solução OpenSessionInViewFilter pois estou trabalhando com ajax, e li que esse filtro não funciona nesse cenário. Se alguém puder se pronunciar, trazendo o “porque” eu agradeceria.

A solução usando OpenSessionInViewInterceptor eu não consegui implementar, seria legal se alguém pudesse trazer isso implementado para auxiliar outras pessoas que também estão com dificuldade.

Solução efetiva:
Utilizar criteria, não sei se é a melhor solução, e se isso acarreta em mal desempenho, vou pesquisar mais a respeito, sugiro que quem for usar faça o mesmo.

J

tem como tu mostrar como ficou teu codigo, pois nao entendi como usar

T
Vc deverá utilizar logo após ter recebido os dados do banco, eu por exemplo estou utilizando um DAO generico então ficou assim:
T t = (T) session.load(classe, id);

Hibernate.initialize(t);

return t;
mas poderia ter feito assim:
Produto produto= (Produto) session.load(Produto.class, id);

Hibernate.initialize(produto);

return produto;
Espero ter ajudado.
J

desculpe…mas essa objeto session? onde crio ele?

T

Vc tem que abrir essa sessão através de uma instancia da classe SessionFactory, e pode variar muito como vc obtem essa instancia.

Sugiro a leitura e prática da apostila gratuita da Caelum FJ-21, vc terá uma boa base para começar a usar hibernate.

J
como utilizo spring + hibernate eu fiz assim.
Usuario usuario = (Usuario) getSession().load(Usuario.class, id );

        Hibernate.initialize(usuario);
porem tenho duvidas em relaçao a esse ID, de onde ele vem, he o id da classe usuario?
T

Sim, esse id é aquele que vc esta procurando, que devera ser passado como como parâmetro para o método que possui esse código que vc postou.

edit¹:
cara, acabei de fazer alguns teste com Hibernate.initialize e acabei constatando que não é a melhor solução, melhor dizendo, nem é uma solução.
Mesmo utilizando esse método, o objeto é inconsistente na view e acaba causando erro 500, vou passar a usar criteria, vamos ver se funciona.

edit²:
testado e aprovado, utilize criteria.
O objeto se mantem na view tranquilo.

Criado 17 de novembro de 2010
Ultima resposta 19 de dez. de 2012
Respostas 25
Participantes 8