Opinem sobre meu DAO GENERICO

51 respostas
T

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();
        }
    }
}

51 Respostas

C

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

T

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!

J

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

jgbt

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

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.

jgbt

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

T

explica melhor hehehehe!

T

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.

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]

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.

F

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

cassio

Titôsca:
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.

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]

Pesquisa sobre o pattern “open session in view”

rodrigoallemand

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

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.

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.

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?

rodrigoallemand

Intercepting Filter

T

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!

rodrigoallemand

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

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

T

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

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!

rodrigoallemand

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

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)?

T

rodrigoallemand:
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

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)?

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

rodrigoallemand

Titôsca:
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!

Sugiro a colocação de um Intercepting Filter pra abrir a transação e commitar no fechamento da sessão, como feito no Hibernate e para Generalizar mais ainda, se for o caso de isso ser um Framework, criar a SessionController<> e uma JPASessionController…

Só uma dica: tente criar os métodos para aquisição e entrega da EntityManager tambem e chama-los no seu DAO. Com isso, vc consegue garantir um ponto unico de acesso, caso vc não use ID…
Outra, tente criar sempre uma Factory para retornar os seus DAOs, retornando uma interface injetando uma classe concreta, implementando o Padrão DataAccessObject mesmo.

ericogr

Eu concordo com o jgbt. Se temos controle transacional, injeção de dependências, aop, etc… com o Spring, para que reinventar a roda e perder tempo criando controles para isso? Está tudo lá, pronto para usar… e será que vale a pena esperar pela implementação JCP? E ela será tão eficaz quanto as soluções existentes logo no início? Eu não esperaria para começar a usar Spring em meus projetos, mas isso é minha opinião.
:slight_smile:

abs

sergiotaborda
Titôsca:
aguardo as críticas
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();
        }
    }
}
Estes dois métodos fazem exatamente a mesma coisa. Esqueça o findToRU e use o findById

um DAO verdadeiramente genérico não define a classe na definição. Encapsule as exepções

GenericDAO<T>
     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();  
         }  
     }

deveria ser:

GenericDAO
     public <T> T findById(Class<T> classObjeto, Integer id) throws DAOException {  
         //    if(!em.isOpen()){  
         em = emf.createEntityManager();  
         //     }  
         try{  
             String sql = StringBuilder("SELECT t FROM ")
                   .append(tableForClass(classObjeto)
                   .append(" t WHERE " ).append("t.codigo = :codigo")
                    .toString();  
             Query e = em.createQuery(sql);  
             e.setParameter("codigo",id);  
             return (T) e.getSingleResult();  
         }finally {  
             em.close();  
         }  
     }  

//com 

DAOException extends RuntimeException

Vc está assumindo que o ID é apenas um campo e que ele é numérico (integer). A menos que isso seja um regra
tenha cuidado. Um ID pode ser composto. De qq forma declare que o ID deve obdecer às regras de implementação de equals e hashCode

Se possivel faça o ID seja um Object e não um Integer

Implemente esse DAO para outras 2 tecnologias que não JPA. Isto é bom porque ajuda a usar menos regras implicitas e a forçar que o DAO seja realmente genérico.

Eu não acho que seja necessário implementar um DAO para cada entidade se vc tiver um mecanismo de intrepretação/tradução de queries acompanhado de uma modelo de persistencia. Caso isto não exista, então sim, é necessário um DAO para cada entidade (e neste contexto deve-se usar o definido na classe e não no método).

rodrigoallemand

ericogr:
Eu concordo com o jgbt. Se temos controle transacional, injeção de dependências, aop, etc… com o Spring, para que reinventar a roda e perder tempo criando controles para isso? Está tudo lá, pronto para usar…

OK! O que falei é que, caso este código seja parte de um framework, faça-o o mais genérico possivel e evite o acoplamento com outros frameworks…

ericogr:

e será que vale a pena esperar pela implementação JCP? E ela será tão eficaz quanto as soluções existentes logo no início?

Vc acha o JPA menos eficiente que o Hibernate?!?
Vc acha o Annotations menos eficiente que o XDoclet (afinal, o que é feito em Annotations era feito em XDoclets nos tempos de 1.5)??
Vc acha que a Validação por anotação, prometida para o proximo Java, vai ser pior que o Hibernate Validator?!?

Eu tambem não… tanto que eu utilizo bastante o Spring nos meus frameworks mas, como disse acima, tente desacoplar… o pessoal pensa no spring como o salvador da pátria!!!
Por exemplo, utilizar o Spring como Factory, forçando um Cast desnecessário… porque não criar UMA classe Factory???
Spring é muuuito bom, mas aprecie com moderação!

rodrigoallemand

E onde vc criaria um metodo “consultarClientesSbrublesSugeridosPeloAmigoDoGerente”, referente somente a entidade Cliente? Ai sim vc criaria uma estrutura de DAO para esta Entidade, correto?!?
Caso sim, então porque não perder mais 5min do seu sistema e fazer uma estrutura para cada entidade, deixando o TypeSafety do Java trabalhar pra vc nos casts?

jgbt

rodrigoallemand:

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)?

ja parei de desenvolver pensando no “SE” ja faz um tempo.
nao costumo implementar nada pensando “vou fazer isso pq se um dia tal coisa acontecer…”.
custumo desenvolver usando o"Keep it simple".
qual a real possibilidade de eu precisar tirar o Spring do meu projeto???
Se um dia isso acontecer, trocar o Spring vai ser o menor dos problemas.
nao acrescente complexidade desnecessaria… pq vou implementar se ja existe e funciona muito bem?

[]'s

jgbt

respondendo:
1 - sim, prefiro usar Hibernate, so o fato de JPA nao Criteria ja seria um motivo.
2 - Nao, prefiro Annotations, nao preciso do ant p/ usar ela.
3 - Nao sei, enqunato nao provarem que eh melhor, fico com o HV.

rodrigoallemand:

Por exemplo, utilizar o Spring como Factory, forçando um Cast desnecessário… porque não criar UMA classe Factory???
Spring é muuuito bom, mas aprecie com moderação!

como é que é??? Cast aonde??? nao entendi

[]'s

T

Pessoal segue o modelo do meu DAO atual:

DAOFactory Interface

public interface DAOFactory <T> {
    
    public T getGenericDAO();
}

SysAguasDAOFactory(Meu factory)

public class SysAguasDAOFactory implements DAOFactory{
    
    public SysAguasDAOFactory() {
    }
    
    public GenericDAO getGenericDAO() {
        return new GenericDAO();
    }
    
}

Meu SessionController que fornece os recursos para DAO abrir transação e cometer as mesmas…

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");
            }
        }
    }
}

Interface GenericRepository

public interface GenericRepository {
    /**
     * @param instance
     */
    public void persist(Object instance);
    
    /**
     * @param instance
     */
    public void delete(Class classeObjeto,Integer codigo);
    
    /**
     * @param id
     */
    
    /**
     * @param instance
     */
    public void update(Object instance);
    
    /**
     * @param id
     * @return
     */
    public <T> T findById(Class<T> classeObjeto, Integer id);
    
    /**
     * @return
     */
    public <T>List findAll(Class<T> classeObjeto);
    
    /**
     * @param begin
     * @param end
     * @return
     */
//    public List<T> findAll(Integer begin, Integer end);
    
    /**
     * @param example
     * @return
     */
//    public List<T> findByExample(T example);
    
    /**
     * @param example
     * @param begin
     * @param end
     * @return
     */
//    public List<T> findByExample(T example, Integer begin, Integer end);
}

[b]Minha implementação do DAO

public class GenericDAO extends SessionController implements GenericRepository {
    
    
    public GenericDAO() {
        super();
        
    }
    
    //public void persist(Object instance) throws EntityExistsException,IllegalStateException,TransactionRequiredException {
    public  void persist(Object instance) throws DAOException {
        em.persist(instance);
    }
    //public void update(Object instance) throws IllegalStateException,IllegalArgumentException,TransactionRequiredException {
    public void update(Object instance) throws DAOException {
        em.merge(instance);
    }
    //public void delete(Class classeObjeto,Integer codigo) throws IllegalStateException,IllegalArgumentException,TransactionRequiredException {
    public void delete(Class classeObjeto,Integer codigo) throws DAOException {
        em.remove(findById(classeObjeto,codigo));
    }
    
    //public <T> T findById(Class<T> classeObjeto, Integer id) throws IllegalStateException,IllegalArgumentException {
    public <T> T findById(Class<T> classeObjeto, Integer id) throws DAOException {
        String sql = new StringBuilder("SELECT t FROM ").append(classeObjeto.getSimpleName())
        .append(" t WHERE " ).append("t.codigo = :codigo").toString();
        Query e = em.createQuery(sql);
        e.setParameter("codigo",id);
        return (T) e.getSingleResult();
        
    }
    //public <T> List  findAll(Class<T> classeObjeto) throws IllegalStateException,IllegalArgumentException {
    public <T> List  findAll(Class<T> classeObjeto) throws DAOException {
        String sql = new StringBuilder("SELECT t FROM ").append(classeObjeto.getSimpleName()).append(" t").toString();
        Query e = em.createQuery(sql);
        List<T> results = (List<T>) e.getResultList();
        return results;
    }

Bom pessoal, infelizmente vocês tem falado algumas coisas de desenvolvimento em ambientes EE que eu ainda não estou familiarizado, estou estudando bastante java e realmente quero me tornar um bom desenvolvedor por isso vim aqui trocar informações sobre meu modelo…

Mas por enquanto não quero utilizar nada pronto (VIDE SPRING) pois quero aprender na mão o que acontece por trás dos panos nesses frameworks que facilitam nossas vidas…

Olhem ai meu DAO agora que irá funcionar para toda entidade… usarei ele para todas e caso seja necessário um DAO especifico eu herdo dele crio um repositorio pra entidade e implemento ele…

O que acharam? Dicas? Críticas? posso melhorar aonde dentro das espectativas minhas usando JAVA SE puro com netbeans hehehehe!

Vlw!

jgbt

ok, Spring nao é o foco da thread.
voltando… vc leu os links que eu passei no meu primeiro post??
pq vc ta concatenado String p/ montar a consulta??
como falei, acho que os metodos de consulta podem ser melhorados.
de uma lida nos links que eu postei.

[]'s

T

jgbt:
ok, Spring nao é o foco da thread.
voltando… vc leu os links que eu passei no meu primeiro post??
pq vc ta concatenado String p/ montar a consulta??
como falei, acho que os metodos de consulta podem ser melhorados.
de uma lida nos links que eu postei.

[]'s

JG,

vou dar uma lida, pelo que vi usam hibernate né? Mas no caso lá as soluções são pra um DAO por entidade pelo que vi… O meu caso é um DAO pra todos e por isso que não consegui enxergar como melhorar essas buscas…

mas, se você me disser que lá tem como fazer mesmo usando a implementação JPA e sem ter que criar um DAO para cada entidade eu vou dar uma olhada lá em casa!

Pro meu problema vai ter como? Um DAO pra todos entidades e melhorar o lance das buscas usando JPA mesmo?

ddduran

Titôsca:
Pessoal segue o modelo do meu DAO atual:

Meu SessionController que fornece os recursos para DAO abrir transação e cometer as mesmas…

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");
            }
        }
    }
}


acho que faltou aqui um lugar que você retorna um EntityManager construido apartir do seu EntityManagerFactory, você poderia se basear no HibernateUtils mesmo usando JPA.

Bom minhas considerações
Por que seu DAO generico herda SessionController?
Ao inves disso não seria melhor você receber (ou injetar) seu Entity Manager no seu construtor? o que diminuiria o acoplamento da sua classe?
outra coisa você passa em varias metodos o Class classeObjeto eu o tornaria tambem um atributo recebido pelo construtor.
Algo como isso

public class GenericDAO <T> implements GenericRepository {
    
    private Class <T> clazz;
    private EntityManager em;
    
    public GenericDAO(EntityManager em, Class<T> clazz) {
       this.em = em;
       this.clazz = clazz;
        
    }

O que acharam? Dicas? Críticas? posso melhorar aonde dentro das espectativas minhas usando JAVA SE puro com netbeans hehehehe!

Vlw!

bom você ta usando JPA que é parte da especificação de EJB que é da JEE :stuck_out_tongue:

jgbt

sim, daria p/ fazer.
vc teria que somente criar os DAOs de cada classe, mas sem nenhuma implementacao.
por exemplo:
no seu DAO generico vc cria um atributo do tipo Class que é setado no construtor por parametro.
tipo:

private final Class class;

    public GenericDao(Class class) {
        this.objectClass = objectClass;
    }

em cada DAO(que vao herdar do generico) especifico que vc criar, no construtor vc da um supper passando a Classe corrente.
isso vai setar seu atributo, e vc usa esse atributo p/ setar tipo generico.
e vai ser esse cara que vai usar no seu DAO generico.

[]'s

T

irei testar a especificação que você stão dizendo junto com a do site da ibm que utiliza Hibernate!

Agora uma dúvida… Vocês dizem ai no meu tópico toda hora injetar algo em algo!

o que seria esse injetar?? me mostrem um exemplo pra mim aprender huheuehue! vlw!

rodrigoallemand

InputStream is = new FileInputStream("beans.xml"); BeanFactory factory = new XmlBeanFactory(is); MinhaClasse minhaClasse = (MinhaClasse) factory.getBean("MinhaClasseBean");

Vc consegue enchergar o Cast?!?

MinhaClasse minhaClasse = minhaFactory.getMinhaClasse();

E a diferença de código?!?

rodrigoallemand

ddduran:
Por que seu DAO generico herda SessionController?
Ao inves disso não seria melhor você receber (ou injetar) seu Entity Manager no seu construtor? o que diminuiria o acoplamento da sua classe?

O problema de injetar, como eu falei, é a dependencia de um container de injeção (ou de inversão)…
Se vc tiver utilizando Spring e achar que isso é o suficiente e infinito no seu sistema, blz! Mas e se isso for um framework?!? E se o cliente não quizer usar ID ou IC?!?
Mais uma vez, Spring é bom mas não é o todo poderoso! Struts já foi esse sucesso um dia…
MAs, se não me engano, é possivel utilizar a anotação do JPa para injetar isso, correto?

Vamos lembrar que, JPA, que é o antigo EntityManager, fez parte da especificação EJB 3 mas é totalmente separado dos SessionBeans e MessageBenas… Tanto que é possivel utilizar JPA em um servidor de aplicação que não seja container EJB… JPA PODE ser OU NÃO JEE… depende de outros artificios… JPA não transforma um projeto em JEE!

ddduran

da uma olhada aqui
http://www.javafree.org/content/view.jf?idContent=1

se você pesquisar aqui no GUJ vai achar muita coisa sobre isso muita discusão mesmo (até brigas)
acho melhor você procurar aqui e ler o que já foi escrito do que eu reiniciar a discusão sobre os beneficios, etc, etc

um exemplo de usar seu DAO desse jeito seria

em = SessionController.getCurrentEntityManager();
     GenericDAO <Cliente> dao = new GenericDAO(em,Cliente.getClass());

     ....
jgbt

InputStream is = new FileInputStream("beans.xml"); BeanFactory factory = new XmlBeanFactory(is); MinhaClasse minhaClasse = (MinhaClasse) factory.getBean("MinhaClasseBean");

Vc consegue enchergar o Cast?!?

MinhaClasse minhaClasse = minhaFactory.getMinhaClasse();

E a diferença de código?!?

caraca… vc ja ouviu falar em autoWireByName???
basicamente eu teria na minha classe:

ClasseQualquer atributo;
get e set p/ esse atributo...

public void fazAlgumaCoisa() {
    atributo.fazAlgo();
}

como esse cara é injetado???
fica como exercicio p/ final de semana vc descobrir…

e vc, consegue ver a diferenca???

[]'s

ddduran

rodrigoallemand:
ddduran:
Por que seu DAO generico herda SessionController?
Ao inves disso não seria melhor você receber (ou injetar) seu Entity Manager no seu construtor? o que diminuiria o acoplamento da sua classe?

O problema de injetar, como eu falei, é a dependencia de um container de injeção (ou de inversão)…
Se vc tiver utilizando Spring e achar que isso é o suficiente e infinito no seu sistema, blz! Mas e se isso for um framework?!? E se o cliente não quizer usar ID ou IC?!?
Mais uma vez, Spring é bom mas não é o todo poderoso! Struts já foi esse sucesso um dia…
MAs, se não me engano, é possivel utilizar a anotação do JPa para injetar isso, correto?

quem precisa de um container para usar esse tipo de estrategia? eu nem uso Spring (discuto até se ele é realmente necessario) :stuck_out_tongue:
ele pode usar como eu escrevi a cima.

Eu disse que o sistema dele agora era JEE? eu preciso de um container EJB para minha aplicação ser JEE?
de que edição é o JPA?

jgbt

outra coisa, me responde uma coisa:
se vc usa isso:

MinhaClasse minhaClasse = minhaFactory.getMinhaClasse();

quer dizer que p/ cada classe vc vai ter um get na sua factory???
muito bom mesmo… evita o cast, mas…

[]'s

T

jgbt:
outra coisa, me responde uma coisa:
se vc usa isso:

MinhaClasse minhaClasse = minhaFactory.getMinhaClasse();

quer dizer que p/ cada classe vc vai ter um get na sua factory???
muito bom mesmo… evita o cast, mas…

[]'s

mas??? eu tow usando assim! minha DAOFactory.getEntidadeDAO();

o que ta errado?

rodrigoallemand

ddduran:
Eu disse que o sistema dele agora era JEE? eu preciso de um container EJB para minha aplicação ser JEE?
de que edição é o JPA?

Só expliquei para ele como funciona a nova disposição do JPA quanto ao EJB, não questionei sua resposta… EJB e JPA agora são independentes, isso que eu tentei explicar…

ddduran

ok, entendi

rodrigoallemand

jgbt:
outra coisa, me responde uma coisa:
se vc usa isso:

MinhaClasse minhaClasse = minhaFactory.getMinhaClasse();

quer dizer que p/ cada classe vc vai ter um get na sua factory???
muito bom mesmo… evita o cast, mas…

[]'s

Vc prefere um método com 2 linhas ou um mais 3 linhas no seu mundo de XML?!? Sem contar que se seu objeto depender de algum atributo na construção, são mais umas 5 linhas… no final… XMLs e mais XMLs… dependencia de um monte JAR… como uma bazuca pra matar formiga!
Eu utilizo Spring com Spring Annotations, que não tem XML… e como a maioria das aplicações contruidas hoje em dia são pequenas/medias, acho que vc ter 1Mb de classes proprias, 3Mb de XML e 15Mb de bibliotecas é um afronto às pessoas que param e pensam em soluções elegantes e embasadas pelos grandes nomes de padrões por ai…

E falando de Spring, quantas vezes vc alterou uma entrada no seu XML de “inversão de controle”?!?!? Já parou pra pensar que muita gente utiliza Spring por ser moda e por “facilitar mudanças” que em projetos com pressão e atmosfera normais nunca acontecem?!? E se vc tivesse fazendo um sistema que precisa de uma fábrica de 600 objetos?!? Vc utilizaria o Spring como singleton ou não?!?!? E a manutenção dos XMLs?!?!? E se sua fabrica ficasse dividida entre Rio, São Paulo, Porto Alegre e India?!? Como miria ser esse controle de mudanças e manutenções?!?
Pense nisso! “Pode ser seu trabalho de fim de semana”. Pensar em como vc pode fazer o desenvolvimento ficar simples, independente, performatico, de facil manutenção e outros requisitos não-funcionais de todos os softwares de grande porte.

rodrigoallemand

OK, vou estudar isso sim, professor… mas avise ao owner da thread, que é quem realmente e indiretamente te perguntou se o GenericDAO dele está legal, que fazer isso que na semana que vem e, depois que eu colocar o meu estudo e o senhor corrigir, ele terá acesso aos fontes e pode aprender como fazer um autoWireByNameComMuitoMaisEquio, ok?

Só me resta rir desses comentários…

rodrigoallemand

Titôsca:
mas??? eu tow usando assim! minha DAOFactory.getEntidadeDAO();
o que ta errado?

Não tem nada de errado se vc tiver levando em consideração o Pattern DAO do Core J2EE…
Existem várias maneiras de uma factory funcionar, e até mesmo as razões dela existir…
Cabe cada um implementar a que mais lhe agrada no contexto do software a ser contruido…
Como a definição de Patterns: Aquilo que resolve o seu problema da maneira mais eficaz possivel! Seja ela com um simples new ou via ID.

T

rodrigoallemand:
Titôsca:
mas??? eu tow usando assim! minha DAOFactory.getEntidadeDAO();
o que ta errado?

Não tem nada de errado se vc tiver levando em consideração o Pattern DAO do Core J2EE…
Existem várias maneiras de uma factory funcionar, e até mesmo as razões dela existir…
Cabe cada um implementar a que mais lhe agrada no contexto do software a ser contruido…
Como a definição de Patterns: Aquilo que resolve o seu problema da maneira mais eficaz possivel! Seja ela com um simples new ou via ID.

ID = Injeção de dependencia???

rodrigoallemand

Yep!

jgbt

rodrigoallemand:

Vc prefere um método com 2 linhas ou um mais 3 linhas no seu mundo de XML?!? Sem contar que se seu objeto depender de algum atributo na construção, são mais umas 5 linhas… no final… XMLs e mais XMLs… dependencia de um monte JAR… como uma bazuca pra matar formiga!
Eu utilizo Spring com Spring Annotations, que não tem XML… e como a maioria das aplicações contruidas hoje em dia são pequenas/medias, acho que vc ter 1Mb de classes proprias, 3Mb de XML e 15Mb de bibliotecas é um afronto às pessoas que param e pensam em soluções elegantes e embasadas pelos grandes nomes de padrões por ai…

E falando de Spring, quantas vezes vc alterou uma entrada no seu XML de “inversão de controle”?!?!? Já parou pra pensar que muita gente utiliza Spring por ser moda e por “facilitar mudanças” que em projetos com pressão e atmosfera normais nunca acontecem?!? E se vc tivesse fazendo um sistema que precisa de uma fábrica de 600 objetos?!? Vc utilizaria o Spring como singleton ou não?!?!? E a manutenção dos XMLs?!?!? E se sua fabrica ficasse dividida entre Rio, São Paulo, Porto Alegre e India?!? Como miria ser esse controle de mudanças e manutenções?!?
Pense nisso! “Pode ser seu trabalho de fim de semana”. Pensar em como vc pode fazer o desenvolvimento ficar simples, independente, performatico, de facil manutenção e outros requisitos não-funcionais de todos os softwares de grande porte.

bom, vc pode me dizer aonde eu apontei o Spring como melhor solucão para tudo?? so mostrei alguns usos, e como qualquer outra coisa, vai ser usado se for necessario.
eu sugeri o Spring para controle de transações, nem mesmo falei em injeção de controle, pq na MINHA opinião, controle de transações não deve ser preocupação do seu codigo, e sim logica de negocio.
vc que falou em cast, so te mostrei que não precisa de cast, é so saber usar.
quanto a questão de xml versus configuracao no codigo, depende muito de opinião pessoal. EU particularmente prefiro em xml, e ja trabalhe SIM em um projeto dividido entre Porto Alegre e Atlanta/USA com mais de 30 desenvolvedores e não tinha problema nenhum em relação a manter esse tipo de arquivo.
como vc parece saber muito sobre o assunto e o foco do topico não é este, não vou discutir mais sobre isso.
se quiser discutir sobre o assunto e ver opiniões diferentes da sua(afinal um forum é p/ isso), pode abrir um topico sobre isso.

[]'s

heitor.rapcinski

rodrigoallemand:

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.

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?

Veja você chama o EntityManager no mesmo lugar que chamaria o DAO Genérico, ao invés de chamar o DAO da entidade X vc chama o EntityManager e trabalha com a entidade X como quiser.

sergiotaborda

E onde vc criaria um metodo “consultarClientesSbrublesSugeridosPeloAmigoDoGerente”, referente somente a entidade Cliente? Ai sim vc criaria uma estrutura de DAO para esta Entidade, correto?!?
Caso sim, então porque não perder mais 5min do seu sistema e fazer uma estrutura para cada entidade, deixando o TypeSafety do Java trabalhar pra vc nos casts?

Existem dois ambientes em que se usa o DAO

  1. O DAO é um deus

Aqui o DAO é o unico elemento da camada de persistencia. O resto do sistema não pode usar o DAO para executar queries genericas e aleatórias.
Neste ambiente cada entidade tem o seu proprio dao e este contém métodos especiais como o “consultarClientesSbrublesSugeridosPeloAmigoDoGerente”. Ele contém , portanto , logica de negocio.
Não é reutilizável para outros dominios e nem para outro mecanismo de persistencia.

  1. O DAO é uma mula

Aqui o DAO não é unico elemento da camada de persistencia. O resto do sistema tem como usar o DAO para executar queries genericas e aleatórias com base num intrepretador e uma forma de definir a query
Neste ambiente um só DAO é usado por todas as entidades que existe no mesmo contexto de persistencia ( no mesmo banco). Ele é utilizável para várias entidades e dominios e para outros mecanismos de persistencia.
Métodos especiais como “consultarClientesSbrublesSugeridosPeloAmigoDoGerente” ou ficam na entidade ele mesma (ex: client.pedidos(semanapassada , hoje) ) ou ficam em serviços ( Roteamento.roteiroPara(List lp) ) ou ficam em repositórios. Os repositorios são os unicos que podem usar o DAO e criar as queries genéricas. Os serviços e as entidades têm que se basear nos métodos do Repositorio. Cada entidade tem um repositório. (Se não gostam palavra Reposiorio, usem Manager)

Giulliano

Titôsca desculpe a demora…então existem diversos exemplos sobre isso…mas conforme dito pesquise pela Open Session On view (usado para sistemas WEB)…

é mais ou menos assim…vc acessa uma Servlet qualquer, um filtro abre a sessão…q quando vc sai da jsp o mesmo filtro fecha a transação… (esta bem resumido)…

Para o seui caso…é só tirar os commit de dentro da classe DAO…e quando vc instaciar um entity manager vc faz o que precisa fazer e depois pega esses managers e dá um commit só…entendeu…

carlos.e.a

Revivendo aqui o topico por te-lo achado muito interessante.

Nao entendi o que o Sergiotaborda quis dizer. Se eu deixar o dao sendo “uma mula” nao vou estar deixando o meu controle muito acoplado a tecnologia usada para persistencia?(No caso um banco de dados). Geralmente uso um mix desses dois que ele falou:

Tem os metodos genericos e mais comuns em qualquer dao(o CRUD) e tenho os metodos do tipo “consultarClientesSbrublesSugeridosPeloAmigoDoGerente”. Nunca tive problemas com essa abordagem e considero que mantenho tudo desacoplado o suficiente da camada de persistencia de modo que se for preciso muda-la so vou ter que reimplementar esses metodos. E se eu usasse a segunda abordagem onde o DAO seria, segundo ele, uma mula o controle ficaria totalmente dependente do tipo de persistencia.

Repito que nao sei se entendi bem e caso a minha forma de implementar a camada de persistencia nao seja a mais correta gostaria que me corrigissem e se possivel indicassem algum material sobre o assunto(e tambem os possiveis problemas dessa abordagem). Geralmente fico “encucado” com problemas de padroes de projeto e sempre que penso estar fazendo errado fico meio preocupado.

Desde ja agradeço a todos!

Criado 25 de outubro de 2007
Ultima resposta 26 de dez. de 2011
Respostas 51
Participantes 13