EJB3 + JPA + DAO como?

Pessoal,

Nao to conseguindo juntar esse quebra cabeça hehehe. Por exemplo, no EJB eu uso o seguinte:

@PersistenceContext private EntityManager entityManager;

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void save(Usuario entity) throws BusinessException {

	try {
		
		factory.getUsuarioDAO().save(entity);
		
	}catch(DAOException e){
		throw new BusinessException("br.com.oi.portal.all.erro.daoerror");
	}catch(Exception e){
		throw new BusinessException("br.com.oi.portal.all.erro.ejberror");
	}finally{
		
	}
}

no UsuarioDAO eu tenho outro
@PersistenceContext private EntityManager entityManager;

que faz o persist … porem esse entityManager no DAO aparece como null. Eu tenho que usar o DAO como um EJB tb ? usando o @EJB ?

usa o EntityManager do bean, que é injetado.

não sei se com a especificação nova existe a necessidade de um DAO…

sem bem q meter um ejbql no bean vai ficar horrivel.

e FICA… rs Ultimamente tenho visto os antigos DAOs serem renomeados para EAOs (Entity Access Object,s e não me engano.) e esses sim são EJBs injetados nos Sessions de fachada.

então os daos viraram session beans ?

Na boa, muito ruim isso, eu so queria separar o DAO pra poder ter uma camada de negocio e outra de persistencia, pra nao ficar tudo junto. Ses tem alguma sugestao em como implementar isso ? seria muito ruim usar um ejb pra negocio e outro pro dao ?

Imagine uma situação onde vc tem um Business de Usuario.java e quer fazer uma query que que retorne todos os usuarios baseado numa seria de criterios, consultas essas que um outro EJB vai precisar usar tambem. Desta forma eu teria que replicar tudo em vez de chamar essa query no DAO .

de outro tópico:

[quote=maquiavelbona]Mais pessoas já se questionaram sobre isso:

http://www.theserverside.com/news/thread.tss?thread_id=40581
http://osdir.com/ml/programming.extreme-programming.databases.agile/2006-05/msg00031.html
http://www.logemann.org/day/archives/000150.html

E mais se procurares pela web.

Até![/quote]

que tal algo assim

/**
 * @author Davy Diegues Duran
 *
 */
public class JPADAO <T> implements DAO <T> {

	private EntityManager em;
	private Class<T> classe;
	
	public JPADAO(EntityManager em, Class<T> classe){
		this.em = em;
		this.classe = classe;
	}
	
	public T atualiza(T o) throws SQLException {
		return (T) em.merge(o);
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#carrega(java.io.Serializable)
	 */
	public T carrega(Serializable chave) throws SQLException {
		return em.find(classe, chave);
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#lista()
	 */
	@SuppressWarnings("unchecked")
	public List<T> lista() throws SQLException {
		Query q = em.createQuery("from " + classe);
		return q.getResultList();
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#lista(java.lang.Object)
	 */
	public List<T> lista(T o) throws SQLException {
		// ainda não há criteria em JPA
		return null;
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#lista(java.lang.Object, java.lang.String[])
	 */
	public List<T> lista(T o, String... propriedadesExcluidas)
			throws SQLException {
		// ainda não há criteria em JPA
		return null;
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#lista(java.lang.String, java.lang.Object[])
	 */
	@SuppressWarnings("unchecked")
	public List<T> lista(String jpql, Object... parametros) throws SQLException {
		Query q = em.createQuery(jpql);
		int index = 0;
		for(Object parametro: parametros)
			q.setParameter(index, parametro);
		
		return q.getResultList();
	}

	/* (non-Javadoc)
	 * @see br.com.teste.dao.DAO#remove(java.lang.Object)
	 */
	public void remove(T o) throws SQLException {
		em.remove(o);
	}

}

só pra exemplificar, muito se discute sobre JPA ter substituindo a necessidade de DAO, mas não acho que seja uma realidade(em alguns é)
imagina colocar um metodo que usa um monte OQL (para generalizar) dentro do seu entity, não seria muito legal, ne?

A não é pra criticar o codigo heim fiz rapidim :), sei que não devia ter SQLException para não expor que é um DAO de banco, etc, etc

mas até que ta bem feito vai :smiley:

não tme um esquema de externalizar as querys ?

no hibernate se nao me engano tem.

eu também não gostei muito da alternativa de EJB DAOs, mas é a única coisa que achei em livros, embora como o pessoal ja dissse, há muitas controvérsias sobre o assunto…

http://www.javalobby.org/java/forums/t33053.html

[quote=Rafaelprp]não tme um esquema de externalizar as querys ?

no hibernate se nao me engano tem.[/quote]

então mais ai você vai deixar todas as querys em xml?
não estamos tantando fugir de usar tando xml e só usar ele quando realmente for aplicavel?

até concordo que nesses casos

update(T o){
      em.merge(o);
}

é meio desnecessario usar um dao, mas imagine que para executar um determinado metodo de acesso ao banco envolva mais ações, ai não vale a pena centralizar a logica?

Atualmente uso extensivamente EJB3 e JPA,
e sugestão do ddduran é mais viável.

Um outro mote para ter DAOs é a capacidade de
reutilização dos processo de persistências quando
o sistema começa a crescer muito, e em muitos casos
tem casos particulares de negócio.

A regra ainda é a mesma, separar a persistência
da camada de negócio e melhorar a componentização.

Bom trabalho.

[quote=Malachai]Na boa, muito ruim isso, eu so queria separar o DAO pra poder ter uma camada de negocio e outra de persistencia, pra nao ficar tudo junto. Ses tem alguma sugestao em como implementar isso ? seria muito ruim usar um ejb pra negocio e outro pro dao ?

Imagine uma situação onde vc tem um Business de Usuario.java e quer fazer uma query que que retorne todos os usuarios baseado numa seria de criterios, consultas essas que um outro EJB vai precisar usar tambem. Desta forma eu teria que replicar tudo em vez de chamar essa query no DAO .[/quote]

O que vc está replicando??? Vc tem um DAO que é um EJB e é INJETADO em outro EJB sem a intrusão de um framework como Spring por exemplo. Todo o acesso ao SGBD fica centrtalizado ali. O que vc está replicando? Existe algum jeito melhor de separar camadas do que DI? Não entendi sua posição.

Tem a opção de deixar as querys acessiveis por toda aplicação atraves do entity.
Basta utilizar a anotação @NamedQuery(name = “nomeDaQuery”, query = “”) no seu entity bean.
Depois use o metodo EntityManager.createNamedQuery(“nomeDaQuery”).

Assim é uma forma de centralizar as queries e poder utilizar em varios locais, sem poluir muito o session bean.

OBS: Tenho duvidas em relacao a arquitetura de uma aplicação q utiliza JSF e EJB3.
Vou começar um projeto semana q vem e estou procurando ideias. Uma delas seria a respeito dessa arquitetura
de camada de negocio e camada de persistencia. Se tiverem mais ideias e exemplos postem ai p/ ter uma ideia.

Vlw!!! :smiley: