Dúvida Injeção de Dependencia no Hibernate [RESOLVIDO]

6 respostas
guihgf_10

Pessoal bateu uma dúvida e como vocês são mais experientes preciso de ajuda; Estou utilizando a injeção de depencias para abrir a conexão e transação do hibernate. Defini como @ApplicationScoped, a minha dúvida é, quais os riscos de eu ter apenas uma transação para a aplicação inteira? Isso é bom ou ruim? É praticamente um singleton correto?

package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenSessionFactory implements ComponentFactory<SessionFactory>
{
	private SessionFactory factory;
	
	@PostConstruct
	public void open()
	{
		try
		{
			ApplicationLog.getInstance().info(this, "Criando Fábrica do Hibernate");
			AnnotationConfiguration configuration= new AnnotationConfiguration();
			configuration.configure();
			factory=configuration.buildSessionFactory();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
			factory=null;
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this,e.getMessage());
			factory=null;
		}
	}
	
	
	@PreDestroy
	public void close()
	{
		try
		{
			ApplicationLog.getInstance().info(this, "Encerrando Fábrica do Hibernate");
			this.factory.close();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this,e.getMessage());
		}
		finally
		{
			this.factory=null;
		}
	}
	
	public SessionFactory getInstance() 
	{
		return factory;
	}

}
package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenSession implements ComponentFactory<Session>
{
	private SessionFactory factory;
	private Session session;
	
	public OpenSession(SessionFactory factory)
	{
		this.factory=factory;
	}
	
	@PostConstruct
	public void open()
	{
		ApplicationLog.getInstance().info(this, "Criando Session do Hibernate");
		try
		{
			this.session=this.factory.openSession();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this,e.getMessage());
		}
	}
	@PreDestroy
	public void close()
	{
		try
		{
			ApplicationLog.getInstance().info(this, "Encerrando Session do Hibernate");
			this.session.close();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this,e.getMessage());
		}
		finally
		{
			this.session=null;
		}
	}

	public Session getInstance() {
		return session;
	}
	
	
}
package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenTransaction implements ComponentFactory<Transaction> 
{
	private Session session;
	private Transaction transaction;
	
	public OpenTransaction(Session session)
	{
		this.session=session;
	}
	
	@PostConstruct
	public void open()
	{
		ApplicationLog.getInstance().info(this, "Abrindo transação do Hibernate");
		try
		{
			this.transaction=session.beginTransaction();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this,e.getMessage());
		}	
	}
	
	@PreDestroy
	public void close()
	{
		ApplicationLog.getInstance().info(this, "Fechando transação do Hibernate");
		this.transaction=null;
	}

	public Transaction getInstance() {
		return this.transaction;
	}
}
package br.com.eplus.dao;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.caelum.vraptor.ioc.Component;
import br.com.eplus.model.Usuario;
import br.com.eplus.util.ApplicationLog;

@Component
public class UsuarioDao
{
	private final Session session;
	private final Transaction transaction;
	
	public UsuarioDao(Session session, Transaction transaction)
	{
		this.session=session;
		this.transaction=transaction;
	}
	
	public void salvarUsuario(Usuario u)
	{
		try
		{
			ApplicationLog.getInstance().info(this, "Salvando novo usuário");
			session.save(u);
			transaction.commit();
		}
		catch(HibernateException h)
		{
			ApplicationLog.getInstance().error(this, h.getMessage());
		}
		catch(Exception e)
		{
			ApplicationLog.getInstance().error(this, e.getMessage());
		}		
	}	
}

6 Respostas

C

Creio que se vc trabalhar com uma só session para toda aplicação como controla a tentativa de manipular o mesmo registro? Porque os usuários que desejam manipular este registro estão na mesma session. Por isto creio que o correto é manter o scopo de sessão ( SessionScoped ).

Hebert_Coelho

Se você for deixar a transação aberta, não vejo como boa prática. Não vejo qual o ganho disso.

Só tome cuidado com o conceito. O @ApplicationScoped não é thread safe.

Esse post pode te ajudar a entender melhor o conceito de @ApplicatioinScoped: http://uaihebert.com/?p=1596&page=7

guihgf_10

Legal o link jakefrog. Seria interessante então eu utilizar uma única SessionFactory para toda a aplicação
(@ApplicationScoped) e @RequestScoped para Transaction e Session (deixando o spring abrir e fechar estes dois a cada requisição)?

Hebert_Coelho

Se você está utilizando o Spring, por que você não usa o próprio sistema de transação dele?

Vou deixar que alguém que entenda melhor de Spring opine aqui. [=

guihgf_10

Na verdade é o vraptor, mas acredito que o ioc dele é feito pelo Spring.

guihgf_10

Bom vou partir da idéia que a SessionFactory busca as configurações do Hibernate e eu só preciso fazer isso uma vez, por isso vou deixar como @ApplicationScoped (economizo tempo e memória). Os demais eu vou deixar como @RequestScoped, onde o vraptor gerencia eles por si próprio, no fim as sequências ficaram:

12:21:43,701 INFO [OpenSessionFactory ] Criando Fábrica do Hibernate
12:21:55,560 INFO [OpenSession ] Criando Session do Hibernate
12:21:55,634 INFO [OpenTransaction ] Abrindo transação do Hibernate
12:21:56,006 INFO [UsuarioDao ] Salvando novo usuário
12:21:56,418 INFO [OpenSession ] Encerrando Session do Hibernate
12:21:56,422 INFO [OpenTransaction ] Fechando transação do Hibernate

Criado 10 de setembro de 2012
Ultima resposta 11 de set. de 2012
Respostas 6
Participantes 3