[quote=sergiotaborda][quote=danielbussade]
Vamos supor um cadastro de Funcionario onde a Entity Funcionario esta definida assim:
@Entity
@Table(name="FUNCIONARIO")
public class Funcionario {
public Funcionario() {
this.dataPrimeiroAcesso=new Date();
this.dataUltimoAcesso=new Date();
this.ativo=true;
}
//Getters e Setters omitidos
[/quote]
Por exemplo, aqui, como vc garante que a segunda data é igual à primeira ?
Deveria ser
public Funcionario() {
this.dataPrimeiroAcesso=new Date();
this.dataUltimoAcesso=dataPrimeiroAcesso;
this.ativo=true;
}
A primeira regra de programação é : Conheça as API que usa.
Se vc investigar sobre hibernate vai descobrir existe um padrão chamado Session-in-View que era usado antigamente, e que básicamente controla a transação por sessão do usuário. Hoje, existem tecnicas mais evoluidas como o uso de ThreadLocal. Procura por HibernateUtils para ver como é isso.
O controle de transação é da aplicação: isto significa que não é do dominio. Logo, não é dos serviços ou repositorios.
A transação é controlada pelo aplicação, então ela tem que ser inicializada/terminada no MBean (explicitamente) ou em um proxy do Serviço (implicitamente). Não antes. Não depois.
bom, além disso um melhor controle de exceções ajudaria. Especialmente o encapsulamento do hibernate abaixo do DAO. Ou seja, ninguem sabe que o hiberante existe excepto o DAO. Isto também é SoC. Cada objeto deve ter apenas uma responsabilidade. Se todos conhecer o hibernate, session, etc… todos sabem demais.
O serviço ficaria então apenas
public class FuncionarioService {
public void criarFuncionario(Funcionario funcionario)throws PersistenceException{
FuncionarioDao dao = new DaoFactory().getFuncionarioDao();
dao.save(funcionario);
}
public void atualizarFuncionario(Funcionario funcionario){
FuncionarioDao dao = new DaoFactory().getFuncionarioDao();
dao.update(funcionario);
}
e o controle de transação, por exemplo, passaria para o MBean
[code]
public void atualizar(){
Session session = hibernateUtils.getSession();
try {
session.beginTransaction();
funcionarioService.atualizarFuncionario(funcionario);
limpar();
preparePesquisar();
session.getTransaction().commit();
} catch (HibernateException e) {
session.getTransaction().rollback();
throw new PersistenceException("Erro ao criar Funcionario",e); //ok
}
}
[/code][/quote]
Então Sérgio eu uso o padrão OpenSession in View em conunto com HibernateUtils desta forma:
package br.com.oticaweb.util;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUtil {
private static Logger logger=Logger.getLogger(HibernateUtil.class);
private static SessionFactory sessionFactory;
private static ThreadLocal<Session> sessions=new ThreadLocal<Session>();
static{
sessionFactory=new AnnotationConfiguration().configure().buildSessionFactory();
}
public static Session openSession(){
if(sessions.get() !=null){
logger.error("There was a session for this thread alredy");
}
sessions.set(sessionFactory.openSession());
return sessions.get();
}
public static void closeCurrentSession(){
sessions.get().close();
sessions.set(null);
}
public static Session currentSession(){
return sessions.get();
}
}
E tenho um Filtro chamado HibernateSessionFilter
package br.com.oticaweb.util;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.Logger;
public class HibernateSessionFilter implements Filter {
private Logger logger = Logger.getLogger(HibernateSessionFilter.class);
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain fc) throws IOException, ServletException {
HibernateUtil.openSession();
try {
HibernateUtil.currentSession().beginTransaction();
fc.doFilter(req, resp);
HibernateUtil.currentSession().getTransaction().commit();
} catch (Exception e) {
try {
if (HibernateUtil.currentSession().getTransaction().isActive()) {
logger.debug("Trying to rollback database transaction after exception");
HibernateUtil.currentSession().getTransaction().rollback();
}
} catch (Exception e1) {
logger.error("Could not rollback transaction after exception!",e1);
}
} finally {
HibernateUtil.closeCurrentSession();
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
O problema desta abordagem que eu estava utilizando e que no Meu ManagedBean nao tinha como ter certeza que o dado foi inserido no banco de dados, pois o Hibernate so efetuava a operacao no commit, q esta definida no Filtro, entao se eu mostrasse uma pagina antes tipo cadastrado com sucesso coreria o risco de estar dando uma mensagem “falsa”.
Agora se o controle de transacoes fica no MBean ai o Service neste caso perde o sentido Sergio, poderia chamar o Dao direto do MBean nao?
Obrigado mais uma vez!