Opinem sobre meu DAO GENERICO

[quote=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![/quote]

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.

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

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:

[code]GenericDAO
public T findById(Class 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
[/code]

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

[quote=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…
[/quote]

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…

[quote=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?[/quote]

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!

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?

[quote=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)?[/quote]

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

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.

[quote=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![/quote]
como é que é??? Cast aonde??? nao entendi

[]'s

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!

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

[quote=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
[/quote]

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?

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

[/quote]
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;
        
    }

[quote]

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

Vlw![/quote]

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

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

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!

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

[quote=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?[/quote]

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!

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

     ....

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?!?[/quote]

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

[quote=rodrigoallemand][quote=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?[/quote]

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?
[/quote]

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?

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

[quote=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[/quote]

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

o que ta errado?