Meu Generic DAO - Opinião e Crítica

Boa tarde pessoal.

Sou novo no mundo Java e muito entusiasmado. Vim do mundo desktop e PHP. Estou criando um programinha para aprendizado de JSF 2 + Hibernate 3. Meu ponto fraco é OO e padrões de projeto. Criei um Generic DAO e gostaria da opinião de vocês. Este negócio de Hibernate com JPA me confunde…rsss
Alguma opinião, crítica, etc?

GenericDAO:

package br.com.futurize.persistencia;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import br.com.futurize.seguranca.PermissaoClasses;
import br.com.futurize.seguranca.PermissaoException;
import br.com.futurize.util.ConfigCadastro;
import br.com.futurize.util.ConstantesGerais;

@SuppressWarnings("unchecked")
public class GenericDAO<T> {

	@SuppressWarnings("rawtypes")
	private Class persistentClass;
	private Session session;

	private String prefixo   = "";
	private String tabela    = "";
	private String fieldId   = "";
	private String fieldNome = "";
	
	@SuppressWarnings("rawtypes")
	protected GenericDAO(Session p_session, Class p_persistentClass) {
		if ((p_session == null) || (!session.isOpen()))
			session = HibernateUtil.getSession();
		else		
			session = p_session;
		
		persistentClass = p_persistentClass;
	}
	
	public Session getSession() {
		return session;
	}

	@SuppressWarnings("rawtypes")
	public Class getPersistentClassLocal(){
		return persistentClass;
	}
	
	public void insert(T obj) throws Exception {		
		Transaction transaction = session.beginTransaction();		
		try {
			
			if (!PermissaoClasses.VerificaPermissao(ConstantesGerais.PERMISAO_INSERT, persistentClass))
				throw new PermissaoException("Permissão Negada para Inserção - " + PermissaoClasses.getDescricaoClasse(persistentClass.getName()));
			
			session.save(obj);
			session.flush();
			transaction.commit();
			
		} catch (Exception e) {
			transaction.rollback();
			throw new Exception(e);
		}	
	}

	public void update(T obj) throws Exception {
		Transaction transaction = session.beginTransaction();
		
		try {
			
			if (!PermissaoClasses.VerificaPermissao(ConstantesGerais.PERMISAO_UPDATE, persistentClass))
				throw new PermissaoException("Permissão Negada para Atualização - " + PermissaoClasses.getDescricaoClasse(persistentClass.getName()));
						
			session.update(obj);
			session.flush();
			transaction.commit();
			
		} catch (Exception e) {
			transaction.rollback();
			throw new Exception(e);
		}	
	}
		
	public void delete(T obj) throws Exception {
		Transaction transaction = session.beginTransaction();
		
		try {
			
			if (!PermissaoClasses.VerificaPermissao(ConstantesGerais.PERMISAO_DELETE, persistentClass))
				throw new PermissaoException("Permissão Negada para Exclusão - " + PermissaoClasses.getDescricaoClasse(persistentClass.getName()));
			
			session.delete(obj);
			session.flush();
			transaction.commit();
			
		} catch (Exception e) {
			transaction.rollback();
			throw new Exception(e);
		}	
	}

	public Integer count(List<Criterion> criterion) throws Exception {
		try {
			
			Criteria criteria = session.createCriteria(persistentClass);
			
			for (Criterion c: criterion)
				criteria.add(c);
			
			criteria.setProjection(Projections.rowCount());
			return ((Integer) criteria.uniqueResult()).intValue();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public List<T> listAll(String fieldOrder, String ord) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			addOrder(criteria, fieldOrder, ord);
			return criteria.list();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}
	
	public List<T> listAll(int first, int max, String fieldOrder, String ord, List<Criterion> criterion) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			addOrder(criteria, fieldOrder, ord);

			for (Criterion c: criterion)
				criteria.add(c);
			
			if (first != 0)
				criteria.setFirstResult(first - 1);

			if (max != 0)
				criteria.setMaxResults(max);

			return criteria.list();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}
	
	public List<T> listAllCadastro(int first, int max, String fieldOrder, String ord, List<Criterion> criterion) throws Exception {
		try {
			
			if (!PermissaoClasses.VerificaPermissao(ConstantesGerais.PERMISAO_CADASTRO, persistentClass))
				throw new PermissaoException("Permissão Negada para Seleção - " + PermissaoClasses.getDescricaoClasse(persistentClass.getName()));
			
			return listAll(first, max, fieldOrder, ord, criterion);
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public T findById(Long id) throws Exception {
		try {
			
			return (T) session.get(persistentClass, id);
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public String findByNome(Long id) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(getFieldId(), id)).setProjection(Projections.property(getFieldNome()));
			criteria.uniqueResult();
			if (criteria.uniqueResult() == null)
				return "";
			else
				return criteria.uniqueResult().toString();
		
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public String findByColumn(Long id, String column) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(getFieldId(), id)).setProjection(Projections.property(column));
			criteria.uniqueResult();
			if (criteria.uniqueResult() == null)
				return "";
			else
				return criteria.uniqueResult().toString();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public String findByColumnValue(String findColumn, String findValue, String fieldReturn) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(findColumn, findValue)).setProjection(Projections.property(fieldReturn));
			if (criteria.uniqueResult() == null)
				return "";
			else
				return criteria.uniqueResult().toString();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public String findByColumnValue(String findColumn, Long findValue, String fieldReturn) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(findColumn, findValue)).setProjection(Projections.property(fieldReturn));
			if (criteria.uniqueResult() == null)
				return "";
			else
				return criteria.uniqueResult().toString();
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public Boolean isUsedCadastro(String findColumnFK, Long findValue) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(findColumnFK, findValue));
			Integer totalResult = (Integer)criteria.setProjection(Projections.rowCount()).uniqueResult();
  			return totalResult > 0;
  		
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public Boolean isUsedCadastro(String findColumnFK, String findValue) throws Exception {
		try {

			Criteria criteria = session.createCriteria(persistentClass);
			criteria.add(Restrictions.eq(findColumnFK, findValue));
			Integer totalResult = (Integer)criteria.setProjection(Projections.rowCount()).uniqueResult();
			return totalResult > 0;
			
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public List<T> findByCriteria(List<Criterion> criterion) throws Exception {
		try {
		
			Criteria criteria = session.createCriteria(persistentClass);

			if (criterion == null)
				return null;

			for (Criterion c: criterion)
				criteria.add(c);

			return criteria.list();
	    
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public List<Object[]> query(String sql) throws Exception {
		try {
			
			Query select = session.createQuery(sql);
			return select.list();

		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	public int sqlUpdate(String sql) throws Exception {
		try {
			
			int rowCount = 0;
			Query query = session.createQuery(sql);
			rowCount = query.executeUpdate();
			return rowCount;
		
		} catch (Exception e) {
			throw new Exception(e);
		}	
	}

	private Criteria addOrder(Criteria criteria, String fieldOrder, String ord) {

		if (!fieldOrder.isEmpty()) {
			if ((ord.toUpperCase().equals("ASC")) || (ord.isEmpty()))
				criteria.addOrder(Order.asc(fieldOrder));

			if (ord.toUpperCase().equals("DESC"))
				criteria.addOrder(Order.desc(fieldOrder));
		}
		return criteria;
	}
		
	//gets e sets

}

ClientesDAO:

package br.com.futurize.persistencia;

import org.hibernate.Session;

import br.com.futurize.dominio.Clientes;

@SuppressWarnings({"rawtypes", "unused"})
public class ClientesDAO extends GenericDAO<Clientes> {

	private Session sessionLocal;
	private Class persistentClassLocal = Clientes.class;

	public ClientesDAO(Session session) {
		super(session, Clientes.class);
		super.setPrefixo("clf");
		super.setPrefixo("clientes");
		super.setFieldId("clf_CLIENTE");
		super.setFieldNome("clf_nome");
		this.sessionLocal = session;
		this.persistentClassLocal = super.getPersistentClassLocal();
	}

}

Muito obrigado a todos e fiquem com Deus
Ademir - BH

Ninguém… :frowning:

É que eu preciso saber se está ok para dar continuidade ao projeto.

Msm assim obrigado pelas 50 visualizações…rsss

Abraços a todos
Ademir

E ae cara?

Então, eu particularmente achei seu DAO muito grande. Não precisa ter tantas funcionalidades assim não. Em OO se a classe tá ficando muito grande, tá na hora de refatorar.

E outra coisa, você usa um try catch apenas para throws? Você pode tirar o try catch e deixar só o throws no método que funciona. :smiley:

[quote=AdemirPinto]Ninguém… :frowning:

É que eu preciso saber se está ok para dar continuidade ao projeto.

Msm assim obrigado pelas 50 visualizações…rsss

Abraços a todos
Ademir[/quote]

Amigo eu achei suas classes interessante… inclusive vc esta usando bastante padrão… e achei legal que aprendeu rápido para quem veio do PHP, quanto tempo vc estudou Java? tem algum documento legal para indicar?

Agora uma dúvida que eu fiquei aqui porque vc cria suas classes genericas e etc… como funciona isso é do proprio Java?

Confesso que a primeira vez que eu olhei, desisti quando vi o tamanho do código…

Achei interessante que você facilitou muito para as implementações reais de DAO…

Uma melhoria que faria é a seguinte:

A transação é importante para executar vários comandos em um bloco só: roda tudo ou nada…

Se no método do DAO você dá begin e commit, perde esse efeito…pois terá um commit a cada comando!

Uma solução seria passar a transação para o construtor do DAO, e outra classe gerenciar begins, commits e rollbacks…

Dá uma olhada no meu DAO:

public class GenericDAOImp&lt;T,ID extends Serializable&gt; implements GenericDAO&lt;T, ID&gt; {
	@PersistenceContext(type=PersistenceContextType.EXTENDED)
	private EntityManager entityManager;
	private final Class&lt;T&gt; classePersistente;

	public GenericDAOImp(){
		this.classePersistente = (Class&lt;T&gt;)
		((ParameterizedType)getClass().getGenericSuperclass())
		.getActualTypeArguments()[0];
	}

	public Class&lt;T&gt; getClassePersistente() {return classePersistente;}
	
	protected final Criteria criaCriteria() {
		return criaSession().createCriteria(getClassePersistente());
	}

	public final Session criaSession() {
		return  (Session)getEntityManager().getDelegate();
	}
	public EntityManager getEntityManager() {return entityManager;}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	@Override
	public Class&lt;T&gt; getObjectClass() {return this.classePersistente;}

	@Override 
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
	public T salvar(T object)  {
		getEntityManager().clear();
		try {
			getEntityManager().persist(object);
		}catch(Exception e){
			e.printStackTrace();
		}
		return object;
	}

	@SuppressWarnings("unchecked")       
	public List&lt;T&gt; todos(String ordem){ 
		StringBuffer queryS = new StringBuffer("SELECT obj FROM "+classePersistente.getSimpleName()+" obj "); 
		if(ordem!=null){
			queryS.append("order by "+ordem);
		}
		Query query = getEntityManager().createQuery(queryS.toString()); 
		return query.getResultList(); 
	}

	@Override 
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
	public T atualizar(T object) {
		getEntityManager().merge(object);
		return null;
	}

	@Override 
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
	public T excluir(T object) {
		try {
			object = getEntityManager().merge(object);
			getEntityManager().remove(object);
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
	public T findById(ID id) {
		return getEntityManager().find(getClassePersistente(), id);
	}

	@Override
	public void refresh(Object object) {
		getEntityManager().refresh(object);
	}

[quote=javablue]E ae cara?

Então, eu particularmente achei seu DAO muito grande. Não precisa ter tantas funcionalidades assim não. Em OO se a classe tá ficando muito grande, tá na hora de refatorar.

E outra coisa, você usa um try catch apenas para throws? Você pode tirar o try catch e deixar só o throws no método que funciona. :smiley: [/quote]

Valeu pelas dicas Javablue,

vou tirar os try e catch. Me fala uma coisa qual a sua sugestão de refatorar minha classe?

Muito obrigado a todos pelas respostas. Vou responder a todos.
Ademir

[quote=AbelBueno]Confesso que a primeira vez que eu olhei, desisti quando vi o tamanho do código…

Achei interessante que você facilitou muito para as implementações reais de DAO…

Uma melhoria que faria é a seguinte:

A transação é importante para executar vários comandos em um bloco só: roda tudo ou nada…

Se no método do DAO você dá begin e commit, perde esse efeito…pois terá um commit a cada comando!

Uma solução seria passar a transação para o construtor do DAO, e outra classe gerenciar begins, commits e rollbacks…

[/quote]

Olá AbelBueno,

obrigado pelo retorno. Vou melhorar esta classe com relação à transção conforme sua ideia. Vc tem uma ideia de como seria uma outra classe pra fazer este controle de transação?

Muito obrigado!
Ademir

[quote=raf4ever]Dá uma olhada no meu DAO:

[code]
public class GenericDAOImp<T,ID extends Serializable> implements GenericDAO<T, ID> {
@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager entityManager;
private final Class<T> classePersistente;

public GenericDAOImp(){
	this.classePersistente = (Class&lt;T&gt;)
	((ParameterizedType)getClass().getGenericSuperclass())
	.getActualTypeArguments()[0];
}

public Class&lt;T&gt; getClassePersistente() {return classePersistente;}

protected final Criteria criaCriteria() {
	return criaSession().createCriteria(getClassePersistente());
}

public final Session criaSession() {
	return  (Session)getEntityManager().getDelegate();
}
public EntityManager getEntityManager() {return entityManager;}

public void setEntityManager(EntityManager entityManager) {
	this.entityManager = entityManager;
}

@Override
public Class&lt;T&gt; getObjectClass() {return this.classePersistente;}

@Override 
@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
public T salvar(T object)  {
	getEntityManager().clear();
	try {
		getEntityManager().persist(object);
	}catch(Exception e){
		e.printStackTrace();
	}
	return object;
}

@SuppressWarnings("unchecked")       
public List&lt;T&gt; todos(String ordem){ 
	StringBuffer queryS = new StringBuffer("SELECT obj FROM "+classePersistente.getSimpleName()+" obj "); 
	if(ordem!=null){
		queryS.append("order by "+ordem);
	}
	Query query = getEntityManager().createQuery(queryS.toString()); 
	return query.getResultList(); 
}

@Override 
@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
public T atualizar(T object) {
	getEntityManager().merge(object);
	return null;
}

@Override 
@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
public T excluir(T object) {
	try {
		object = getEntityManager().merge(object);
		getEntityManager().remove(object);
	}catch(Exception e){
		e.printStackTrace();
	}
	return null;
}

@Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRED) 
public T findById(ID id) {
	return getEntityManager().find(getClassePersistente(), id);
}

@Override
public void refresh(Object object) {
	getEntityManager().refresh(object);
}

[/code][/quote]

raf4ever,

como que funciona este EntityManager? Isso é spring? Desculpe a ignorância.

Obrigado pela resposta.
Ademir

[quote=dtxk][quote=AdemirPinto]Ninguém… :frowning:

É que eu preciso saber se está ok para dar continuidade ao projeto.

Msm assim obrigado pelas 50 visualizações…rsss

Abraços a todos
Ademir[/quote]

Amigo eu achei suas classes interessante… inclusive vc esta usando bastante padrão… e achei legal que aprendeu rápido para quem veio do PHP, quanto tempo vc estudou Java? tem algum documento legal para indicar?

Agora uma dúvida que eu fiquei aqui porque vc cria suas classes genericas e etc… como funciona isso é do proprio Java?[/quote]

Fala dtxk,

obrigado pelos elogios…rsss Estou só começando, na verdade eu juntei uns Generic DAO daqui do forum, juntei conforme minha necessidade e aquilo que eu ia compreendendo, não queria uma coisa muito sofisticada e complexa. Sobre como aprendi, além de ser formado em Ciencia da Computação pela Universidade Federal de Viçosa-MG, pra mim a net é a sala de aula e o google é meu livro…rssss
Eu usei gerericas para exatamente ter como extender nas classes especificas: como ClienteDAO, FornecedorDAO, ContaBancariaDAO, etc…acho que é por este motivo…ou estou falando bobagem???rsss

Abraços
Ademir

Eu sou contra herdar um dao genérico em cada um de seus daos. O dao genérico possui inúmeros comportamentos que geralmente o dao filho nunca vai usar, gerando herança desnecessária. Ao invés disso, injete o dao genérico pelo construtor, e faça uso dele quando for necessário.

Tenho que enfrentar problemas enormes de herança graças a daos genéricos desnecessários. :?

[quote=von.juliano]Eu sou contra herdar um dao genérico em cada um de seus daos. O dao genérico possui inúmeros comportamentos que geralmente o dao filho nunca vai usar, gerando herança desnecessária. Ao invés disso, injete o dao genérico pelo construtor, e faça uso dele quando for necessário.

Tenho que enfrentar problemas enormes de herança graças a daos genéricos desnecessários. :? [/quote]

Obrigado von.juliano pelas suas criticas que são de muito valia. Vc tem aí um exemplo de injeção de dao generico?

Abraços
Ademir

eu achei legal por que deu para ver que você caprichou… pensou em fazer tomando cuidado com os detalhes…até por quÊ ficou grande… confesso que também não li tudo com calma, só dei uma olhadinha.

Algumas dicas que a experiência e alguns estudos demonstram para agente:

Evite deixar o dao gerenciar sua session do hibernate… assim fica mais dificil de você sempre fecha-la da forma correta… sempre passe a sessão para o seu Dao e caso ela esteja fechada lance uma exceção por exemplo… dao não deveria abrir sessão, o seu modelo, seila, seu BO deve abrir a sessão, passar uma sessão válida para os daos fazerem o que tiverem que fazer e ai no BO você comita ou da rollback caso tenha dado erro, assim vai comitar ou rollbackear tudo o que foi feito (a menos que a regra de negócio seja comitar só uma metade caso só ela tenha dado certo e dar rollback no que não deu, o que eu nunca vi, e mesmo que seja essa a ideia, dao não é lugar de regra de negócio, é lugar de operação com o banco pura e simples). Não se esqueça de ter um try catch no seu BO dando commit no final do try, rollback no catch.

quanto aos try catchs do dao, eles serão necessários caso você queira fazer alguma coisa em caso de erro (obvio, é a utilidade mais básica do try catch…). Como acabei de indicar você a deixar o rollback em outro lugar ele a principio não teria mais utilidade, mas eu te indico que em caso de erro você gere um log no dao dizendo o que vocÊ estava tentando inserir/atualizar/busca/deletar… logando por exemplo a classe e método do seu dao e o toString do pojo que você estava tentando… fazer o que estava fazendo, assim é facil detectar o que aconteceu no futuro em caso de algum erro. Ja que seria esse log só no caso de erro, ele deve ficar no catch, tornando-o necessário, não se esqueça de dar o throw depois disso para avisar a camada de cima (um BO por exemplo) que o erro aconteceu, assim ela pode tomar a decisão que precisar, dar o rollback na sessão do hibernate, avisar o controller para que este então redirecione para uma tela de erro por exemplo. Eu gosto de além de logar no dao quais eram as informações que deu erro ao inserir por exemplo, logar no modelo alguma coisa do tipo “erro ao …”.

Procure deixar seus pojos sempre com o fech Lazy, para ficar mais leve ao obter suas entidades no banco. é possivel que vocÊ tenha problemas de Lazy Innicialization, a dica abaixo resolve.

Para gerenciar como você abre sua sessão do hibernate (e como fecha), eu te aconselharia ver o padrão Open Session In View…

essa é uma leitura muito boa, mas isso é só mais para frente…

bom… no demais parabéns… gostei muito do seu dao e se me permite peço para pegar ele e adapta-lo…

Ao invés de extender o dao genérico:

class ClientesDAO extends GenericDAO<Clientes>você o passa pelo construtor:

[code]class ClientesDAO {

ClientesDAO(GenericDAO dao) {...}

}[/code]Aí você cria os métodos que o ClienteDao deve ter, que provavelmente serão uma quantidade muito menor do que os que existem no dao genérico, e o utiliza quando necessário.

Uma dica para quem está começando: herança é um perigo, muito cuidado!

[quote=von.juliano]Ao invés de extender o dao genérico:

class ClientesDAO extends GenericDAO<Clientes>você o passa pelo construtor:

[code]class ClientesDAO {

ClientesDAO(GenericDAO dao) {...}

}[/code]Aí você cria os métodos que o ClienteDao deve ter, que provavelmente serão uma quantidade muito menor do que os que existem no dao genérico, e o utiliza quando necessário.

Uma dica para quem está começando: herança é um perigo, muito cuidado![/quote]

Fala von.juliano. Cara agora vc me deixou confuso…rsss Uma das ideias de herança não é remover código duplicado e coloca-lo na classe pai? Como assim que herança é perigoso?
Como que funciona este negocio de injeção do dao generico?

Abraços e muito obrigado
Ademir

[quote=maior_abandonado]eu achei legal por que deu para ver que você caprichou… pensou em fazer tomando cuidado com os detalhes…até por quÊ ficou grande… confesso que também não li tudo com calma, só dei uma olhadinha.

Algumas dicas que a experiência e alguns estudos demonstram para agente:

Evite deixar o dao gerenciar sua session do hibernate… assim fica mais dificil de você sempre fecha-la da forma correta… sempre passe a sessão para o seu Dao e caso ela esteja fechada lance uma exceção por exemplo… dao não deveria abrir sessão, o seu modelo, seila, seu BO deve abrir a sessão, passar uma sessão válida para os daos fazerem o que tiverem que fazer e ai no BO você comita ou da rollback caso tenha dado erro, assim vai comitar ou rollbackear tudo o que foi feito (a menos que a regra de negócio seja comitar só uma metade caso só ela tenha dado certo e dar rollback no que não deu, o que eu nunca vi, e mesmo que seja essa a ideia, dao não é lugar de regra de negócio, é lugar de operação com o banco pura e simples). Não se esqueça de ter um try catch no seu BO dando commit no final do try, rollback no catch.

quanto aos try catchs do dao, eles serão necessários caso você queira fazer alguma coisa em caso de erro (obvio, é a utilidade mais básica do try catch…). Como acabei de indicar você a deixar o rollback em outro lugar ele a principio não teria mais utilidade, mas eu te indico que em caso de erro você gere um log no dao dizendo o que vocÊ estava tentando inserir/atualizar/busca/deletar… logando por exemplo a classe e método do seu dao e o toString do pojo que você estava tentando… fazer o que estava fazendo, assim é facil detectar o que aconteceu no futuro em caso de algum erro. Ja que seria esse log só no caso de erro, ele deve ficar no catch, tornando-o necessário, não se esqueça de dar o throw depois disso para avisar a camada de cima (um BO por exemplo) que o erro aconteceu, assim ela pode tomar a decisão que precisar, dar o rollback na sessão do hibernate, avisar o controller para que este então redirecione para uma tela de erro por exemplo. Eu gosto de além de logar no dao quais eram as informações que deu erro ao inserir por exemplo, logar no modelo alguma coisa do tipo “erro ao …”.

Procure deixar seus pojos sempre com o fech Lazy, para ficar mais leve ao obter suas entidades no banco. é possivel que vocÊ tenha problemas de Lazy Innicialization, a dica abaixo resolve.

Para gerenciar como você abre sua sessão do hibernate (e como fecha), eu te aconselharia ver o padrão Open Session In View…

essa é uma leitura muito boa, mas isso é só mais para frente…

bom… no demais parabéns… gostei muito do seu dao e se me permite peço para pegar ele e adapta-lo…[/quote]

Fala maior_abandonado…muito boas as suas explanações. Achei muito interessante sobre o Open Session In View.
Alguém aqui da lista está usando ele a risca ou fez alguma adaptação. O que eu acho mais complicado em usar o filter pra controlar transação seria o controle de qual erro aconteceu e um tratamento para mostrar para o usuário. Mas a ideia é muito interessante e estou querendo usa-la.

Abraços
Ademir

[quote]Fala maior_abandonado…muito boas as suas explanações. Achei muito interessante sobre o Open Session In View.
Alguém aqui da lista está usando ele a risca ou fez alguma adaptação. O que eu acho mais complicado em usar o filter pra controlar transação seria o controle de qual erro aconteceu e um tratamento para mostrar para o usuário. Mas a ideia é muito interessante e estou querendo usa-la. [/quote]

então… na prática eu até deveria ter alguma coisa anotada, para alterar conforme necessidade, mas um padrão de start para algumas coisas que são repetitivas, muitas aplicações tem mas eu não tenho… apesar disso acho que qualquer implementação que siga essa idéia é válida… o importante é você colocar alguma coisa para abrir a sessão do hibernate antes de você precisar dela, ela ficar disponivel onde você precisar (você pode deixa-la na sessão ou usar um objeto de uma classe chamada ThreadLocal em uma classe segundaria como um HibernateUtils por exemplo) e depois de ter feito o que precisa fechar a conexão… você pode usar filters para isso (e se você diz que está começando é o que eu te indico agora), mas normalmente usa-se algum framework MVC, se você estiver usando, geralmente os frameworks de MVC (ao menos os não muito antigos) que você possa usar tem alguma funcionalidade semelhante que possa te ajudar nisso, os PhaseListeners do JSF, os Interruptors do struts, indo um pouco mais além poderia ser injetada a sessão na sua classe, ai entraria num spring ou num EJB por exemplo (assunto para você estudar mais para frente, bem legal). Resumidamente existem várias formas de seguir este padrão, depende do framework que você está usando, da arquitetura da aplicação…

editando…

esse exemplo ai que você colocou foi o primeiro resultado no google né… eu tinha procurado algum link que eu achasse legal mas não achei… (ai falei para você procurar :D), esse exemplo coloca para dar o commit e o rollback no filter… eu não gosto muito dessa abordagem por que não me parece viavel o filter saber se deu algum erro ou não (isso é assunto de algum componente dentro do controller e/ou do modelo, esse filter ai é só para disponibilizar e fechar a sessão), se ele não deve saber, não é ele que deve dar o commit ou o rollback, ou seja, para mim ele não deveria gerenciar essa parte transacional…

o filter ainda deve lançar uma exceção em caso de não conseguir abrir a sessão (e assim o usuário deveria ser redirecionado para uma tela de erro)… mas se ele conseguiu abrir, deu o chain e chamou a aplicação e deu erro na hora de fechar, ai a minha opinião é que vocÊ não deveria alterar qual a página que o usuário vai, apenas logar o problema. Isso pode ser caracteristico de bug, sei la, você fechou a sessão no meio da aplicação e ao tentar fechar no filter ja estava fechada, ou perdeu a conexão com o banco no meio do processamento… mas se o usuário iria para uma página normal na aplicação acho que ele deveria continuar indo, se ele iria para a página que você iria exibir um erro especifico e você impedir que vá para lá para mostrar outro erro de que você não conseguiu fechar a conexão, você pode estar mascarando um outro problema…

O porque é um assunto que já foi muito discutido, e há muito material sobre, então vou te passar alguns artigos e um link do guj, que explicam o porque de usar composição ao invés de herança:

http://www.guj.com.br/java/2542-composicao-versus-heranca
http://www.artima.com/designtechniques/compoinh.html


http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/pat/herancavscomposicao.htm

Blz? Flw! :thumbup:

[quote=maior_abandonado][quote]Fala maior_abandonado…muito boas as suas explanações. Achei muito interessante sobre o Open Session In View.
Alguém aqui da lista está usando ele a risca ou fez alguma adaptação. O que eu acho mais complicado em usar o filter pra controlar transação seria o controle de qual erro aconteceu e um tratamento para mostrar para o usuário. Mas a ideia é muito interessante e estou querendo usa-la. [/quote]

então… na prática eu até deveria ter alguma coisa anotada, para alterar conforme necessidade, mas um padrão de start para algumas coisas que são repetitivas, muitas aplicações tem mas eu não tenho… apesar disso acho que qualquer implementação que siga essa idéia é válida… o importante é você colocar alguma coisa para abrir a sessão do hibernate antes de você precisar dela, ela ficar disponivel onde você precisar (você pode deixa-la na sessão ou usar um objeto de uma classe chamada ThreadLocal em uma classe segundaria como um HibernateUtils por exemplo) e depois de ter feito o que precisa fechar a conexão… você pode usar filters para isso (e se você diz que está começando é o que eu te indico agora), mas normalmente usa-se algum framework MVC, se você estiver usando, geralmente os frameworks de MVC (ao menos os não muito antigos) que você possa usar tem alguma funcionalidade semelhante que possa te ajudar nisso, os PhaseListeners do JSF, os Interruptors do struts, indo um pouco mais além poderia ser injetada a sessão na sua classe, ai entraria num spring ou num EJB por exemplo (assunto para você estudar mais para frente, bem legal). Resumidamente existem várias formas de seguir este padrão, depende do framework que você está usando, da arquitetura da aplicação…
[/quote]

Então maior_abandonado, com relação à session eu vou usar algum start msm, eu uso o PhaseListeners para segurança, poderia usar ele pra iniciar e fechar a sessão? Agora e a transação como eu poderia fazer? Neste meu projeto eu estou usando JSF 2, JPA 2 e Hibernate 3. Não estou querendo pindurar muitos frameworks para nao ficar confuso. Mas qualquer sugestão é bem vinda.

Abraços e mais uma vez muito obrigado.
Ademir

[quote=von.juliano]O porque é um assunto que já foi muito discutido, e há muito material sobre, então vou te passar alguns artigos e um link do guj, que explicam o porque de usar composição ao invés de herança:

http://www.guj.com.br/java/2542-composicao-versus-heranca
http://www.artima.com/designtechniques/compoinh.html


http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/pat/herancavscomposicao.htm

Blz? Flw! :thumbup: [/quote]

Obrigado von.juliano, vou ler todos, nao pesquisei sobre este assunto é porque nem sabia dessa historia de composição vs herança…rsss

Abraços
Ademir