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