Opinem sobre meu DAO GENERICO

E ai pessoal,

Estou criando uma aplicacao aqui e ao invés de criar um DAO para cada entitdade eu fiz um DAO que dá pra utilizar com qualquer tabela! Mas queria umas opiniões se é legal se ficou bom e tudo!

aguardo as críticas

import br.com.sysaguas.entidade.DAO.EntityInterface;
import br.com.sysaguas.entidade.Tipoquarto;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NamedQuery;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class GenericDAO<T> implements GenericRepository<T> {
    
    private EntityManagerFactory emf = null;
    private EntityManager em = null;
    
    public GenericDAO() {
        if(emf == null){
            this.emf = Persistence.createEntityManagerFactory("SysAguasPU");
        }
    }
    
    public void persist(T instance) {
        em = emf.createEntityManager();
        try{
            em.getTransaction().begin();
            em.persist(instance);
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }
    public void update(T instance) {
        em = emf.createEntityManager();
        try{
            em.getTransaction().begin();
            em.merge(instance);
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }
    public void delete(Integer codigo, String tipoObjeto) {
        //  if(!em.isOpen()){
        em = emf.createEntityManager();
        //   }
        try{
            em.getTransaction().begin();
            em.remove(findToRU(codigo,tipoObjeto));
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }
    private T findToRU(Integer id,String tipoObjeto) throws IllegalStateException{
        String sql = ("SELECT t FROM "+ tipoObjeto +" t WHERE t.codigo = :codigo");
        Query e = em.createQuery(sql);
        e.setParameter("codigo",id);
        return (T) e.getSingleResult();
    }
    
    public T findById(Integer id,String tipoObjeto) throws IllegalStateException{
        //    if(!em.isOpen()){
        em = emf.createEntityManager();
        //     }
        try{
            String sql = ("SELECT t FROM "+ tipoObjeto +" t WHERE t.codigo = :codigo");
            Query e = em.createQuery(sql);
            e.setParameter("codigo",id);
            return (T) e.getSingleResult();
        }finally {
            em.close();
        }
    }
}

Um DAO reutilizável. Parabéns, :stuck_out_tongue:

vlw! mas podem criticar! se ele me gerar algum problema futuro no desenvolvimento da aplicação! só quero mesmo aprender os pros e contras e se tem uma forma melhor ! mas vlw hehehe!

Obs: Uma ótima pratica seria você colocar as transactions na sua camada de serviço, deixando o acesso para o DAO…

os metodos de consulta podem ser melhorados.
de uma olhada nesses links:
http://www.hibernate.org/328.html

mesma ideia, so usando hibernate
bons estudos.

[]'s

normalemnte a transação fica fora do DAO, embnora eu não use assim, mas as boas práticas dizem que uma transação não é responsabilidade do DAO…e sim da classe de negócios…

se vc inicia uma transação e vai salvando vários objetos diferentes aí no último save dá um erro…vc simplesmente não faz commit e dá um rollback…

do jeito que vc fez já foi feito o commit e já era…de resto esta bacana.

eu usaria o Spring para controlar minhas transacoes, nao escreveria mais essas mesmas linhas de codigo varias vezes e me preocuparia somente com o business da minha aplicação. :smiley:

[]'s

explica melhor hehehehe!

[quote=Giulliano]normalemnte a transação fica fora do DAO, embnora eu não use assim, mas as boas práticas dizem que uma transação não é responsabilidade do DAO…e sim da classe de negócios…

se vc inicia uma transação e vai salvando vários objetos diferentes aí no último save dá um erro…vc simplesmente não faz commit e dá um rollback…

do jeito que vc fez já foi feito o commit e já era…de resto esta bacana.[/quote]

Me da um exemplo só pra mim visualizar melhor!

eu entendi que a parte de começar uma transação não deveria estar no dao não é isso??

como seria então mais ou menos?

[i]Olha se estou pensando certo::

Dentro da camada de negocios teria um Factory que me criaria um entitymanager e abriria uma transação e devolveria esse entitymanager para mim!

ai todo metodo do DAO teria que tbém receber o entitymanager que tá com a transação em aberto para fazer as operações no banco???[/i][b]

Acho desnecessário a utilização de um DAO quando você utiliza JPA, eu constumo colocar as consultas com @NamedQuery na Entidade quando referencia apenas uma entidade e no Pacote quando referencia várias entidades. O EntityManager pode ser injetado nas classes de serviço e ele genérico o suficiente para realizar todas as operações de persistência.

só a minha opnião.

eu utilizo em alguns DAO generico q faço um cara chamado Param que contém um Map<String, Serializable> onde coloco atributos para preencher uma query dinâmica, fica muito bom e prático! Fico bom o seu DAO

[quote=Titôsca][quote=Giulliano]normalemnte a transação fica fora do DAO, embnora eu não use assim, mas as boas práticas dizem que uma transação não é responsabilidade do DAO…e sim da classe de negócios…

se vc inicia uma transação e vai salvando vários objetos diferentes aí no último save dá um erro…vc simplesmente não faz commit e dá um rollback…

do jeito que vc fez já foi feito o commit e já era…de resto esta bacana.[/quote]

Me da um exemplo só pra mim visualizar melhor!

eu entendi que a parte de começar uma transação não deveria estar no dao não é isso??

como seria então mais ou menos?

[i]Olha se estou pensando certo::

Dentro da camada de negocios teria um Factory que me criaria um entitymanager e abriria uma transação e devolveria esse entitymanager para mim!

ai todo metodo do DAO teria que tbém receber o entitymanager que tá com a transação em aberto para fazer as operações no banco???[/i][b][/quote]

Pesquisa sobre o pattern “open session in view”

eu usaria o Spring para controlar minhas transacoes, nao escreveria mais essas mesmas linhas de codigo varias vezes e me preocuparia somente com o business da minha aplicação. :smiley:

[]'s
[/quote]

Tambem concordo que “tecnicamente” o controle transacional deve ficar fora dos DAOs, mas sempre vi coisas desse tipo sem muito problemas. O que eu faço, normalmente é colocar um método no DAO pra controlar isso e criar uma anotação colocada no método de negócio informando o tipo de transação, ou melhor, se o commit deve ser feito ao fim ou não. Se eu quizer no meio do método comitar, eu chamo o método do DAO. A abertura
da transação fica, no meu caso, normalmente em um interceptor.

[quote=heitor.rapcinski]Acho desnecessário a utilização de um DAO quando você utiliza JPA, eu constumo colocar as consultas com @NamedQuery na Entidade quando referencia apenas uma entidade e no Pacote quando referencia várias entidades. O EntityManager pode ser injetado nas classes de serviço e ele genérico o suficiente para realizar todas as operações de persistência.

só a minha opnião.[/quote]

Estive pensando nisso esses dias. Esse é o primeiro projeto grande que eu utilizo JPA. São 600 entidades + ou -… já imaginaram a zona que iriamos ter no fim do projeto???

Mas Heitor, como vc imagina fazer este controle? Dentro dos objetos de negocio mesmo ou dentro das entidades?

Intercepting Filter

Certo gente… agora uma dúvida que estou tendo…

geralmente fazemos a implementação de um DAO para cada ENTIDADE né… o certo é isso mesmo ter um DAO pra cada entidade??

Não se utiliza um DAO central que trabalha com todas as entidades nao? E se for necessario algo mais especifico em uma entidade extender do dao padrao e implementar da forma necessaria nesse caso???

Sobre a questão de transação:

Se o dao não ficarai responsavel por isso logo ele não iria criar o entitymanager certo???

Então meu down receberia como parametro um entitymanager que é criado pela minha regra de negocio?

Vlw!

Eu normalmente faço assim:

  • Um SessionController que é uma classe que só abre e fecha sessões e transações, faz commit e coisas do tipo
  • Um GenericRepository<> (encare como repository uma interface que esse seu DAO ai implementaria)
  • Um GenericDAO<> extends SessionController implements GenericRepository<>
  • Um AsteristicoRepository extends Generic Repository
  • Um AsteristicoDAO extends GenericDAO

Na verade, o meu AsteriscoRepository ou AsteristicoDAO só tem realmente os métodos especializados a ele.
De resto, o “basicão” fica nos genericos

por isso que eu volto a falar, pq implementar isso se o Spring implementa de maneira totalmente transparente esse controle???
configure suas transações e pronto, porque controlar isso no codigo?

[]'s

Eu normalmente faço assim:

  • Um SessionController que é uma classe que só abre e fecha sessões e transações, faz commit e coisas do tipo
  • Um GenericRepository<> (encare como repository uma interface que esse seu DAO ai implementaria)
  • Um GenericDAO<> extends SessionController implements GenericRepository<>
  • Um AsteristicoRepository extends Generic Repository
  • Um AsteristicoDAO extends GenericDAO

Na verade, o meu AsteriscoRepository ou AsteristicoDAO só tem realmente os métodos especializados a ele.
De resto, o “basicão” fica nos genericos
[/quote]

Galera seguindo a ideia de vocês de separar as transações das funções do DAO eu fiz seguindo o modelo do Rodrigo! Vejam se captei bem a idéia

Classe SessionController


package br.com.sysaguas.entidade.DAO;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.EntityTransaction;

public class SessionController {
    
    protected static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("SysAguasPU");
    protected EntityManager em = null;
    protected EntityTransaction transaction;
    private EntityTransaction transaction2;
    
    public SessionController() {
        
    }
    public void beginTransaction(){
        if(em == null){
            em = emf.createEntityManager();
            em.getTransaction().begin();
        }else if(em.getTransaction().isActive()){
            System.out.println("Já possuímos uma transação em aberto, finalize antes de iniciar outra");
        }else{
            em.getTransaction().begin();
        }
    }
    public void commitTransaction(){
        if(em != null){
            if(em.getTransaction().isActive()){
                try {
                    em.getTransaction().commit();
                } finally {
                    em.close();
                    em=null;
                }
                
            }else{
                System.out.println("Não há transações ativas para commit");
            }
        }
    }
    
}

A minha classe SessionController só tem as funções basicas para abrir uma transação e ETC. Agora meu GenericDAO herda a classe SessionController e adquiri as funcionalidades de abrir e remeter uma transação correto???

package br.com.sysaguas.entidade.DAO;
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;



public class GenericDAO<T> extends SessionController implements GenericRepository<T> {
    
    
    public GenericDAO() {
        super();
        
    }
    
    public void persist(T instance) throws EntityExistsException,IllegalStateException,TransactionRequiredException {
        em.persist(instance);
    }
    public void update(T instance) throws IllegalStateException,IllegalArgumentException,TransactionRequiredException {
        em.merge(instance);
    }
    public void delete(Integer codigo, String tipoObjeto) throws IllegalStateException,IllegalArgumentException,TransactionRequiredException {
        em.remove(findToRU(codigo,tipoObjeto));
    }
    private T findToRU(Integer id,String tipoObjeto) throws IllegalStateException,IllegalArgumentException {
        String sql = ("SELECT t FROM "+ tipoObjeto +" t WHERE t.codigo = :codigo");
        Query e = em.createQuery(sql);
        e.setParameter("codigo",id);
        return (T) e.getSingleResult();
    }
    
    public T findById(Integer id,String tipoObjeto) throws IllegalStateException,IllegalArgumentException {
        String sql = ("SELECT t FROM "+ tipoObjeto +" t WHERE t.codigo = :codigo");
        Query e = em.createQuery(sql);
        e.setParameter("codigo",id);
        return (T) e.getSingleResult();
        
    }
    public List<T> findAll(String tipoObjeto) throws IllegalStateException,IllegalArgumentException {
        String sql = ("SELECT t FROM "+ tipoObjeto +" t");
        Query e = em.createQuery(sql);
        List<T> results = (List<T>) e.getResultList();
        return results;
    }
}

Bom agora a minha camada de regra de negocio tem a opção de abrir e remeter a transação a hora que quiser bastando chamar as funções proprias do meu DAO que herdou da classe SessionController, seria isso a ideia de tirar a transação das funções do down? e dar mais liberdade pra camada de negocio controlar as mesmas??

Tem algo mais que posso tar aplicando no meu modelo para otimiza-lo e torna-lo ainda mais reutilizavel ???

Vlw!

[quote=jgbt]por isso que eu volto a falar, pq implementar isso se o Spring implementa de maneira totalmente transparente esse controle???
configure suas transações e pronto, porque controlar isso no codigo?

[]'s[/quote]

Eu sempre procuro faz\er as coisas dependerem somente do Java, e não dos Frameworks… e se um dia vc tirar o Spring pra usar uma inversão de controle nativa do Java (quando existir, afinal, esse é um dos pontos do JCP para o proximo JEE)?

[quote=rodrigoallemand][quote=jgbt]por isso que eu volto a falar, pq implementar isso se o Spring implementa de maneira totalmente transparente esse controle???
configure suas transações e pronto, porque controlar isso no codigo?

[]'s[/quote]

Eu sempre procuro faz\er as coisas dependerem somente do Java, e não dos Frameworks… e se um dia vc tirar o Spring pra usar uma inversão de controle nativa do Java (quando existir, afinal, esse é um dos pontos do JCP para o proximo JEE)?[/quote]

Chegou olhar ai a minha implementação ??? Pra ver se captei sua ideia?