Controle de Transações do hibernate

olá pessoal

gostaria de saber qual a melhor forma de se controlar transações do hibernate junto com o vraptor se é do modo que foi apresentado no capitulo 8 da apostila fj-28 da caelum implementando uma classe ComponentFactory, ou se é como o código abaixo (apostila exemplo do guj) ou de alguma outra forma diferente dessas?

gostaria de opniões.

obrigado

package br.com.guj.hibernateTransaction;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;

public class HibernateHelper {
	private static final SessionFactory sessionFactory;
	private static final ThreadLocal sessionThreadLocal = new ThreadLocal();
	private static final ThreadLocal transactionThreadLocal = new ThreadLocal();
	static {
		try {
			sessionFactory = new Configuration().configure()
					.buildSessionFactory();
		} catch (RuntimeException e) {
			e.printStackTrace();
			throw e;
		}
	}

	public static Session currentSession() {
		if (sessionThreadLocal.get() == null) {
			Session session = sessionFactory.openSession();
			sessionThreadLocal.set(session);
		}
		return (Session) sessionThreadLocal.get();
	}

	private static void closeSession() {
		Session session = (Session) sessionThreadLocal.get();
		if (session != null) {
			session.close();
		}
		sessionThreadLocal.set(null);
	}

	static void beginTransaction() {
		if (transactionThreadLocal.get() == null) {
			Transaction transaction = currentSession().beginTransaction();
			transactionThreadLocal.set(transaction);
		}
	}

	static void commitTransaction() {
		Transaction transaction = (Transaction) transactionThreadLocal.get();
		if (transaction != null && !transaction.wasCommitted()
				&& !transaction.wasRolledBack()) {
			transaction.commit();
			transactionThreadLocal.set(null);
		}
		closeSession();
	}

	static void rollbackTransaction() {
		Transaction transaction = (Transaction) transactionThreadLocal.get();
		if (transaction != null && !transaction.wasCommitted()
				&& !transaction.wasRolledBack()) {
			transaction.rollback();
			transactionThreadLocal.set(null);
		}
		closeSession();
	}
}

Se você usa o vraptor3 você deve apenas declarar um componente que cuida disso tudo para você. Sendo assim basta você injetar sua session nas classes que você precisa.

Na verdade o vraptor delega tudo isso ao provider, sendo o padrão do vraptor usar Spring.

Dê uma olhada no link http://vraptor.caelum.com.br/documentacao/componentes-utilitarios-opcionais/, procure por Hibernate Session e SessionFactory. Além disso há componentes para JPA também.

Com essa configuração basta você fazer um DAO assim, por exemplo:

[code]@Component
public class UserDAO {
private final Session session;

public UserDAO(Session session) {
    this.session = session;
}

public void store(User user) {
session.merge(user);
}

}[/code]

ok garcia e se eu utilizar a classe abaixo

[code]package mapeamento.infra;

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

import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;

@Component
public class CriadorDeSessoes implements ComponentFactory{

private final SessionFactory factory;
private Session session;

public CriadorDeSessoes(SessionFactory factory)
{
	this.factory = factory;
}

@PostConstruct
public void abre(){
	this.session = factory.openSession();
}

public Session getInstance() {
	
	return this.session;
}

@PreDestroy
public void fecha(){
	this.session.close();
}

}
[/code]

consigo utilizar o dao assim

package mapeamento.dao;

import java.util.List;

import mapeamento.modelo.Cidade;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import br.com.caelum.vraptor.ioc.Component;

@Component
public class CidadeDao {

	private Session session;
	
	public CidadeDao(Session session)
	{
		this.session = session;
	}
	
	public boolean Adiciona(Cidade cidade)
	{
		Transaction t = session.beginTransaction();
				
		List l = session.createCriteria(Cidade.class).add(Restrictions.eq("Nome", cidade.getNome()))
		.add(Restrictions.eq("uf", cidade.getUf())).list();
		if(l.size()==0)
		{
			session.save(cidade);
			t.commit();
			return true;
		}
		return false;		
	}
	
	public void atualiza (Cidade cidade)
	{
		Transaction t = session.beginTransaction();
		session.merge(cidade);
		t.commit();
	}
	
	public void remove(Cidade cidade)
	{
		Transaction t = session.beginTransaction();
		session.delete(cidade);
		t.commit();
	}
	
	public List<Cidade> lista()
	{
		return this.session.createCriteria(Cidade.class).addOrder(Order.asc("Nome")).list();
	}
		
	
	public Cidade carrega(Long id)
	{
		return (Cidade) this.session.load(Cidade.class, id);
	}
}

o que eu queria é tirar os

      Transaction t = session.beginTransaction();
      ...
      t.commit();

de todos os métodos e deixá-los na session para ela controlar, entende?

para mim fazer somente

this.session.save(objeto); 

ou

this.sesssion.delete(objeto)

ou controlar a transação em cada método é sempre a melhor opção?

cvinicios, sim, você pode tranquilamente remover as transações. O Vraptor cuida disso para você através do Spring.

Para mim a classe CriadorDeSessoes não precisa existir, já que isso o vraptor já faz. Na classe CidadeDAO você pode remover todos as linhas que você citou sim sem problemas.

Só não esqueça de declarar o componente no web.xml.

<context-param> <param-name>br.com.caelum.vraptor.provider</param-name> <param-value>br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider</param-value> </context-param>

se vc não quiser se preocupar faça como o garcia falou… se vc quiser fazer na mão vc resolve com um interceptor

Referência de post semelhante: http://www.guj.com.br/posts/list/198219.java