Generic DAO

14 respostas
P

Caros,

Estou implementando um DAO Genérico, porém tenho algumas dúvidas que não encontrei, nem no fórum nem pela web.

Bom, li estes links:

http://www.hibernate.org/328.html
http://www-128.ibm.com/developerworks/java/library/j-genericdao.html
http://aujava.wordpress.com/2006/08/09/generic-dao-and-more/
http://www.dhptech.com/node/18
http://www.java2s.com/Code/Java/Hibernate/GenericDaoCreate.htm

e fiz uma implementação de um DAO Genérico, que vos passo:

//AbstractDAO.java

package com.marcosperon.dao;

import java.util.List;

public interface AbstractDAO <DomainObject, KeyType> {

    public DomainObject load(KeyType id) throws Exception;

    public void update(DomainObject object) throws Exception;

    public void delete(DomainObject object) throws Exception;

    public void save(DomainObject object) throws Exception;

    public void deleteById(KeyType id);

    public List<DomainObject> getList();

    public void deleteAll();

    public int count();

}

e uma implementação usando hibernate:

//HibernateAbstractDAO.java

package com.marcosperon.dao.hb;

import com.marcosperon.dao.AbstractDAO;
import com.marcosperon.hb.HibernateUtility;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.hibernate.Session;

/**
 *
 * @author Marcos Peron
 */
public abstract class HibernateAbstractDAO<T extends Serializable, KeyType extends Serializable>
    implements AbstractDAO<T, KeyType>  {

    @SuppressWarnings(value = "unchecked")
    protected Class<T> domainClass = getDomainClass();

    public HibernateAbstractDAO() {
    }

    @SuppressWarnings(value = "unchecked")
    public T load(KeyType id) {
        return ((T)getSession().load(domainClass, id));
    }

    public void update(T obj) {
        getSession().update(obj);
    }

    public void save(T obj) {

        getSession().save(obj);
    }

    public void saveOrUpdate(T obj) {
        HibernateUtility.beginTransaction();
        getSession().saveOrUpdate(obj);
        HibernateUtility.commitTransaction();
    }

    public void delete(T t) {
        getSession().delete(t);
    }

    @SuppressWarnings(value = "unchecked")
    public List<T> getList() {
        Session s = getSession();
        return(s.createCriteria(domainClass).list());
    }

    public void deleteById(KeyType id) {
        Object obj = load(id);
        getSession().delete(obj);
    }

    public void deleteAll() {
        getSession().createQuery("delete " + domainClass.getName()).executeUpdate();
    }

    public int count() {
        List list = getSession().createQuery("select count(*) from " + domainClass.getName() + " x").list();
        Integer count = (Integer) list.get(0);
        return(count.intValue());
    }

    protected Session getSession() {
        return(HibernateUtility.getSession());
    }

    @SuppressWarnings(value = "unchecked")
    protected Class getDomainClass() {
        if (domainClass == null) {
            ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
            domainClass = (Class) thisType.getActualTypeArguments()[0];
        }
        return domainClass;
    }
}

Bom, se eu tiver então um Bean chamado de Bean:

//Bean.java
package com.marcosperon.beans;

import java.io.Serializable;

public class Bean implements Serializable, Comparable<Long> {

    private static final long serialVersionUID = 1;

    private Long id;

    public Bean() {
        //hello do something here
    }

    private void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public int compareTo(Long obj) {
        //...
    }

    public boolean equals(Object obj) {
       //...
    }

    public int hashCode() {
        //...
    }
}

e o Bean Person que estende pessoa:

//Person.java

package com.marcosperon.beans;

public class Person extends Bean {

    private String firstName;

    private String lastName;

    private String personId;

    private boolean active = false;

    public Person() {
        super();
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setName(String name) {
        if (name == null) {
            return;
        }
        if ("".equals(name)) {
            return;
        }
        int iSpacePosition = name.lastIndexOf(" ");
        if (iSpacePosition > -1) {
            setFirstName(name.substring(0, iSpacePosition - 1));
            setLastName(lastName = name.substring(iSpacePosition + 1));
        } else {
            setFirstName(name);
            setLastName("");
        }
    }

    public String getName() {
        StringBuffer fullName = new StringBuffer(getFirstName().length() + getLastName().length() + 1);
        fullName.append(getFirstName());
        if (!("".equals(getLastName()))) {
            fullName.append(" ");
            fullName.append(getLastName());
        }
        return fullName.toString();
    }

    public String getPersonId() {
        return personId;
    }

    public void setPersonId(String personId) {
        this.personId = personId;
    }
}

Bom, agora implementando um DAO para cada um, usando da herança, eu faria:

//BeanDAO.java

package com.marcosperon.dao;

import com.marcosperon.beans.Bean;

public interface BeanDAO<DomainObject> extends AbstractDAO<DomainObject, Long> {
}
//PersonDAO.java

public interface PersonDAO<Person> extends BeanDAO<Person> {

	public List getByName(String name);

}

Ok, até ai tudo bem. isso funciona maravilhosamente BEM.

Porém, se eu criasse outro Bean que estende Person, como Student, e eu quisesse Herdar também os dados da interface PersonDAO, como faria?
Lembrando que eu já passei o tipo para o Generics acima ().

Bom, eu poderia na interface PersonDAO, fazer assim:

//PersonDAO.java

public interface PersonDAO<T extends Person> extends BeanDAO<T> {

	public List getByName(String name);

}

e a interface do Student

//StudentDAO.java

public interface StudentDAO<T extends Person> extends PersonDAO<T> {

	public List getGroups();

}

E na inicialização a minha implementação criar StudentDAO pd = new StudentDAOImpl();

mas quando rodo, essa parte da implementação do hibernate dá erro:

@SuppressWarnings(value = "unchecked")
    protected Class getDomainClass() {
        if (domainClass == null) {
            ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
            domainClass = (Class) thisType.getActualTypeArguments()[0];
        }
        return domainClass;
    }

Porém, se eu fizesse a interface de Student já vir tipada o Generics, ia funcionar numa boa.

Então minha dúvida é essa, como fazer para não perder a possibilidade de herdar também os DAOs Genéricos e pais, sem ter que determinar um tipo no ultimo DAO.

Será que me fiz entender?

Se algúem tiver alguma luz…

Obrigado

Abraços

14 Respostas

J

NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/

M

juniorsatanas:
NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/

Seu blog? :lol:

P

O Exemplo é bom, mas eu gostaria de poder fazer assim:

HibernatePersonDAO<Person> p = new HibernatePersonDAO<Person>();

e em tempo de execução pegar Person no HibernateAbstractDAO.

Assim eu poderia fazer que HibernatePersonDAO extendesse HibernateBeanDAO e teria um DAO Genérico e acima de tudo, com herança dos metodos de acesso ao banco de dados, já que Person é um Bean.

Isso fica mais prático quando eu criar um HibernateStudentDAO que extende HibernatePersonDAO, pois eu poderia ter um getStudentForClass no StudentDAO mas ele herdaria o getPersonByFirstName do PersonDAO, afinal, Student é um Person.

me fiz entender?

O Problema é que se eu manter o Generic até a ultima classe, esse código:

protected Class getDomainClass() {
        if (domainClass == null) {
            ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();            
            domainClass = (Class) thisType.getActualTypeArguments()[0];
        }
        return domainClass;
    }

retorna o erro:

Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
        at com.marcosperon.dao.hb.HibernateAbstractDAO.getDomainClass(HibernateAbstractDAO.java:86)
        at com.marcosperon.dao.hb.HibernateAbstractDAO.<init>(HibernateAbstractDAO.java:26)
        at com.marcosperon.dao.hb.HibernateBeanDAO.<init>(HibernateBeanDAO.java:24)
        at com.marcosperon.dao.hb.HibernatePersonDAO.<init>(HibernatePersonDAO.java:24)
        at com.marcosperon.test.TestAll.main(TestAll.java:25)

sendo que TestAll é:

public class TestAll {

    public TestAll() {
    }
    
    public static void main(String []args) {
        HibernatePersonDAO<Person> p = new HibernatePersonDAO<Person>();
    }

}

alguma idéia?

Grato desde já

T

Maurício Linhares:
juniorsatanas:
NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/

Seu blog? :lol:

como assim meu blog???

G

juniorsatanas:
NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/

MUITO PRAZER SENHOR URUBATAN…É UMA HONRA CONHECE-LO…

:lol:

N

juniorsatanas:
NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/

Afffff…que lixo de pessoa, você deveria sentir :oops:

Plagio na cara larga… :thumbdown:

Receba todo o ódio do GUJ

:evil:

A

juniorsatanas:
NO MEU BLOG TU ENCONTRA ISSO:

http://www.urubatan.com.br/2006/12/27/dao-generico-um-exemplo-a-pedidos/


SEU BLOG?

Que moleque sujo… hehehehe

[color=darkred]Deve ser aquelas crianças contadora de historia e mentirosa…[/color] :twisted:
[size=9]Que feio isso!!![/size]

NO MEU BLOG…
foi ótimo…!

R

Tsc tsc tsc… cade o VERDADEIRO dono do blog pra ler isso?

U

to aqui :smiley:

valeu pelo link hehehehe

mas chegar se adonando do blog assim …
só falta aparecer um post la que não foi escrito por mim agora :smiley:
hehehe

M

Merece um L.A.I. ( Losango Aberto Invertido ). :evil:
Tomando coisas dos outros, que feio…

J
EU SEMPRE VOU  ESTUDAR, LER ETC.. 

                            ISSO ME DA O DIREITO DE CHAMAR DE MEU !HAHAHHAHAH

urubatan , É UM PROGRAMADOR EDUCADO E SABE QUE FOI SÓ UMA BRINCADEIRA !

QUASE QUE EU FUI EXPULSO DO GUJ HAHAHHAHHAH

B

flamess flamesss ea resposta nada!

M

Sendo assim.

Aew povo… cuidado com o MEU GUJ. o MEU HOTMAIL.
Parem de estudar o MEU JAVA.

Só seus argumentos não é o suficiente para dizer que algo é seu.

@benflodin
Cara… seu nome me da medo… aquelas pilulas loucas o.0

T

Vou fechar isso.
Pior que flame war é flame war ressuscitada; não sei como é que o pessoal encontra essas velharias.
(É claro que sei que é pelo Google, mas acho absurdo o cara não perceber que a discussão morreu há muito tempo).

Criado 3 de agosto de 2007
Ultima resposta 7 de mai. de 2009
Respostas 14
Participantes 13