DAO Generico - um exemplo a pedidos

Bom, no blog da Caelum a um tempo atras fizeram um POST sobre um DAO genérico, meio bizarro
Bom, eu uso um DAO genérico a algum tempo, mas o meu DAO genérico tm algumas features a mais do que o mostrado no post da caelum …

Neste exemplo eu ja deixo os metodos para fazer um query by example prontinho, usando a API de criteria do Hibernate …

bom, chega de enrolação, vamos a alguns exemplos …

primeiro, crio uma interface para este DAO …

package br.com.techoffice.site.dao;

import java.io.Serializable;
import java.util.List;

public interface TOBaseDao {
    public Class getObjectClass();
	public T save(T object);
	public T load(PK primaryKey);
    public T get(PK primaryKey);
	public List listAll();
	public List findByExample(final T example);
	public T findOneByExample(final T example);
	public List listAll(final int first,final int max);
	public int listAllPageCount();
	public List findByExample(final T example,final int first,final int max);
	public int findByExamplePageCount(final T example);
    public void update(T object);
    public void delete(T object);
    public void rebind(T object);
}

onde o método getObjectClass() deve retornar a classe de trabalho deste DAO, a mesma passada no parâmetro T quando a interface for estendida …

e a implementação desta interface, fica mais ou menos assim:

package br.com.techoffice.site.dao.impl;

import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.type.Type;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import br.com.techoffice.site.dao.TOBaseDao;
import br.com.techoffice.site.dao.TODaoListener;

@Transactional(propagation = Propagation.REQUIRED, timeout = 20)
public abstract class TOBaseHibernateDao extends HibernateDaoSupport implements TOBaseDao, PropertySelector {
    private static final Log logger = LogFactory.getLog(TOBaseHibernateDao.class);
    private final Class objectClass;

    public TOBaseHibernateDao(final Class objectClass) {
        this.objectClass = objectClass;
    }

    @SuppressWarnings(”unchecked”)
    public Class getObjectClass() {
        return objectClass;
    }

    public int findByExamplePageCount(final T example) {
        final List l = findByExample(example);
        final Integer i = new Integer(l.size());
        return i.intValue();
    }

    public int listAllPageCount() {
        final List l = listAll();
        final Integer i = new Integer(l.size());
        return i.intValue();
    }

    /*
     * (non-Javadoc)
     *
     * @see br.ufrgs.hcpa.template.dao.GetNetBaseDao#findOneByExample(T)
     */
    public T findOneByExample(final T example) {
        final List res = findByExample(example, 0, 1);
        if ((res != null) && (res.size() == 1)) {
            return res.get(0);
        } else {
            return null;
        }
    }

    public T save(final T object) {
        try {
            final Session s = getSession(false);
            s.save(object);
            s.flush();
            return object;
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    public void update(final T object) {
        try {
            final Session s = getSession(false);
            s.update(object);
            s.flush();
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    public void rebind(final T object) {
        try {
            getSession(false).refresh(object);
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    public void delete(final T object) {
        try {
            getSession(false).delete(object);
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    @SuppressWarnings(”unchecked”)
    public T load(final PK primaryKey) {
        try {
            final Session s = getSession(false);
            final Object o = s.load(objectClass, primaryKey);
            return (T) o;
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    @SuppressWarnings(”unchecked”)
    public T get(final PK primaryKey) {
        try {
            final Session s = getSession(false);
            final Object o = s.load(objectClass, primaryKey);
            return (T) o;
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    @SuppressWarnings(”unchecked”)
    public List listAll() {
        try {
            final Session s = getSession(false);
            final Criteria c = s.createCriteria(objectClass);
            addOrderToCriteria(c);
            return c.list();
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

     @SuppressWarnings(”unchecked”)
    public List findByExample(final T example) {
        try {
            final Session s = getSession(false);
            final Criteria c = s.createCriteria(objectClass);
            c.add(Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this));
            addOrderToCriteria(c);
            addPropertiedToCriteria(c, example);
            return c.list();
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    protected void addPropertiedToCriteria(final Criteria c, final T example) {
    }

    @SuppressWarnings(”unchecked”)
    public List findByExample(final T example, final int first, final int max) {
        try {
            final Session s = getSession(false);
            final Criteria c = s.createCriteria(objectClass);
            c.add(Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this));
            addPropertiedToCriteria(c, example);
            addOrderToCriteria(c);
            if (first != 0) {
                c.setFirstResult(first);
            }
            if (max != 0) {
                c.setMaxResults(max);
            }
            return c.list();
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    @SuppressWarnings(”unchecked”)
    public List listAll(final int first, final int max) {
        try {
            final Session s = getSession(false);
            final Criteria c = s.createCriteria(objectClass);
            addOrderToCriteria(c);
            if (first != 0) {
                c.setFirstResult(first);
            }
            if (max != 0) {
                c.setMaxResults(max);
            }
            return c.list();
        } catch (final HibernateException ex) {
            TOBaseHibernateDao.logger.error(ex);
            throw convertHibernateAccessException(ex);
        }
    }

    protected void addOrderToCriteria(Criteria c) {
    }

    public boolean include(Object propertyValue, String propertyName, Type type) {
        if((propertyValue!=null) && (propertyValue instanceof String)){
            return !”".equals(((String)propertyValue).trim());
        }
        return propertyValue!=null;
    }
}

onde o método addOrderToCriteria, permite que subclasses deste DAO ordenem as consultas …
o método addPropertiedToCriteria permite que subclasses adicionem propriedades não incluidas pelo hibernate nas consultas …
e o método include combinado com o setPropertySelector da classe Example é uma melhoria adicionada a pouco tempo, que faz o mesmo que o addPropertiedToCriteria, mas de forma automática, ou seja, inclui as propriedades PK e FK também na QBE …

Bom, depois disto tudo, só falta criar o DAO para alguma entidade persistida pelo Hibernate, como por exemplo uma classe Curriculo …

Criamos a interface do nosso DAO:

package br.com.techoffice.site.dao;

import br.com.techoffice.site.data.Curriculo;

public interface CurriculoDao extends TOBaseDao{
}

e logo depois a implementação deste DAO:

package br.com.techoffice.site.dao.impl;

import net.java.dev.springannotation.annotation.Bean;
import br.com.techoffice.site.dao.CurriculoDao;
import br.com.techoffice.site.data.Curriculo;

@Bean(name="curriculoDao")
public class CurriculoDaoImpl extends TOBaseHibernateDao implements CurriculoDao {
	private static final long serialVersionUID = 1L;

	public CurriculoDaoImpl() {
        super(Curriculo.class);
    }
}

acho que era isto, o que acharam deste DAO genérico?
pela minha experiência, ele resolve de maneira estupidamente fácil em torno de 60% dos meus problemas de persistencia, nos outros 40% ai é necessário criar algum outro metodo de pesquisa especializado para cada situação …

mas acho que é esta a ideia das coisas genéricas, facilitar a maior parte do trabalho e permitir que a menor parte seja feita com um pouquinho de trabalho extra :) o que vocês acham?

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

47 comments so far

  1. Alexandre December 27, 2006 9:04 pm

    PERFEITO ESSE DAO!

    Urubatan muito bom post. Muito bem explicado!!!

    Parabens amigo!!!

  2. Rodrigo Guedes de Souza December 27, 2006 11:27 pm

    Urubatan eu tinha visto este seu DAO num workshop no webdays, ficou muito bom mesmo …..

  3. Gécen December 28, 2006 7:29 am

    Parabéns pelo trabalho que vem realizando pela comunidade, há algum tempo acompanho, então resolvi deixar meu recado…

  4. Thiago December 28, 2006 2:02 pm

    Opa Uburatan ta show esse dao genérico, parabéns.

    Tenho umas duvidas simples.

    esse Propagation.REQUIRED está dizendo que a transação é obrigatória para todos os métodos? aquele mesmo esquema quando declarado via xml?

    E a respeito do include ai, você explicou mas eu fiquei viajando, poderia explicar de outra forma ou passar algum link?

    Como você está utilizando o HibernateDaoSuport, teria alguma vantagem se utilizasse o método getHibernateTemplate() e/ou utilizar aquele esquema da interfacer HibernateCallback ?

    Uma correção besta é que no método get está utilizando load ou invés de get.

  5. Urubatan January 2, 2007 1:51 pm

    Valeus Gécen :D
    Thiago,
    o Propagation.REQUIRED é do spring, e sim, quando ele esta anotando uma classe diz que todos os metodos requerem uma transação …

    quanto ao include, o esquema é que o QueryByExample do Hibernate não inclui campos de relacionamento e PKs, aquele include é chamado quando eu chamo
    [java]
    Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this)
    [/java]

    ou seja, é o callback do property selector do hibernate apenas …

    e quanto a HibernateTemplate X convertHibernateAccessException(ex);
    uso a segunda opção por que acho mais bonito só, mas não vejo nenhuma razão concreta para usar uma ou a outra abordagem …
    :D

  6. Thiago January 3, 2007 6:48 pm

    Olá Urubatan, entendi agora, vlw.

    Só mais uma duvida.
    E a respeito do objectClass que é passado como construtor das classes concretas, ele é realmente preciso já que estamos passando o tipo via generics? eu vi no blog da caleum um artificio que não precisaria dessa classe, conforme no link abaixo:

    http://blog.caelum.com.br/2006/10/29/brincando-com-generics-o-bizarregenericdao/
    o que você acha dessa solução?

  7. Tetsuo January 3, 2007 7:59 pm

    Eu tb escrevi um pouco sobre a classe que é passada no construtor (ou melhor, sobre a ‘mágica’ necessária pra eliminá-lo): http://javapub.blogspot.com/2006/12/generics-reflection-hierarquias-de.html

    No fim, eu achei melhor manter essa passagem por parâmetro do que me aventurar nessa zona obscura :)

  8. Diogo Cabral January 8, 2007 12:55 pm

    Oi,

    O dao ficou muito bom. Gostaria de saber se você não acha mais interessante algo como “return listAll().size()” no lugar de instanciar um Integer nos métodos de page count?

    Abraços

  9. Urubatan January 8, 2007 1:23 pm

    realmente seria melhor …
    não lembro por que esta implementado desta forma, deve ter ficado assim em alguma das metamorfoses sofridas por este DAO durante o tempo de vida dele e eu não prestei atenção :S

    Vaoeu a dica :D

  10. Juan Damasceno January 29, 2007 8:47 pm

    Legal, muito boa implementação, existiria alguma forma de injetar o objectClass pelo Spring?

  11. Diego Pires Plentz February 12, 2007 8:52 am

    Urubatan, por curiosidade, porque você chama o flush() após o save() e update()?

  12. Urubatan February 12, 2007 9:10 am

    sim, é possivel injetar o objectClass pelo spring …

    e diego, eu realmente não lembro o por que do flush, acho que no projeto em que eu fiz isto, estava dando algum bug de batch update e eu tentei resolver assim antes de desabilitar o batch update do hibernate …

  13. ronildojunior February 14, 2007 12:58 pm

    Muito bom o DAO
    So uma duvida… nao seria melhor ter uma classe de negocio e colocar a anotacao dizendo que é requirido uma trasacao nela
    por exemplo:

    @Transactional(propagation = Propagation.REQUIRED, timeout = 20)
    public class ContaCorrente(){
    public retirar(){
    ContaDAO conta = factory.getContaDAO();
    UsuarioDAO usuario = factory.getUsuarioDAO();

    }
    }

    assim todos os DAOs estariam dentro de uma mesma transacao… eu faco uma implementacao assim

  14. Urubatan February 14, 2007 1:17 pm

    A vantagem desta abordagem é que a configuração mais externa é a que vale.
    por exemplo, estou dizendo que os metodos do DAO requerem uma transação, isto não quer dizer uma transação nova …
    por tanto, se no business, o metodo necessitar de uma transação, sera criada uma transação para aquele metodo, e todas as chamadas de dao de dentro daquele metodo utilizarão a mesma transação, por tanto, todas as chamadas estarão dentro da mesma transação …
    assim a transação sera maior, e ainda assim atomica.

    mas caso o metodo do business não precisar de uma transação, serão criadas pequenas transações para cada chamada a um metodo de um DAO.

    ou seja, fica valendo a maior transação :D

  15. Mário Dantas February 16, 2007 1:29 pm

    Olá Urubatan, primeiramente parabéns pelo trabalho, tenho uma dúvida sobre transação.
    Por exemplo em uma transação em que eu tenha q inserir dados de uma nova venda e dados de itens dessa venda, essa implementação do Dao genérico contempla esse tipo de situação ou tenho que fazer isso por fora.

    inicio da transacao

    daoVenda.salvar(venda);
    daoItens.salvar(itens);

    fim da transacao

    algo onde a transação deveria ser mais ou menos assim, um exemplo tosco só para ter um idéia.

    Mais uma vez parabéns pela iniciativa.

  16. Urubatan February 16, 2007 1:57 pm

    Mário, da uma olhada no meu comentário anterior que explica exatamente isto …

  17. Mário Dantas February 16, 2007 4:55 pm

    Beleza, pensei que com objetos de dao’s diferentes ele fazia diferentes transacoes.
    Valeu.

  18. ronildo April 9, 2007 4:03 pm

    Ola

    Copiando o que vc escreveu:
    A vantagem desta abordagem é que a configuração mais externa é a que vale.
    por exemplo, estou dizendo que os metodos do DAO requerem uma transação, isto não quer dizer uma transação nova

    Gostaria de saber como vc fez para trabalhar com essa abordagem, o seu artigo explica detalhes de como funciona o DAO generic, que por sinal é muito bom, mas nao explica como fazer o controle de transação. Vc tem algum material explicando como fazer ?

    Obrigado.

  19. Urubatan April 13, 2007 4:58 pm

    Ronildo, desculpe a demora na resposta, não tinha visto a pergunta …
    o controle de transações funciona exatamente como em um session bean com CMT, ou seja, vale a transação de maior escopo …
    demarcação para a classe vale para todos os métodos
    demarcação no método sobre escreve a da classe

    e se tem todas as opções de propagação de transações que existem nos EJBs.
    mais informações sobre isto na documentação dos EJBs ou na documentação do spring :D

  20. Lucas Húngaro April 17, 2007 5:48 pm

    Urubatan, gostei da sua implementação do TOBaseHibernateDao e passei a utilizar algo bem semelhante como base para meus Daos.

    Utilizo também uma factory para os Daos, mas estou com um problema com as transações:

    Erro: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

    Pesquisei bastante sobre isso, mas não encontrei uma solução. Consigo fazer com o funcione se chamar getSession(true), isto é, permitindo que uma transação seja criada nesse momento, o que não é recomendado, pelo que li.

    Como você configura seu applicationContext para usar essa implementação?

    Outra dúvida, relativa à pergunta do Mário Dantas: como eu consigo começar e finalizar uma transação “por fora” dos Daos, já que eles não expõe os métodos relativos à session?

  21. Thiago April 17, 2007 6:16 pm

    Dê uma conferida aqui Lucas.

    http://pastebin.co.uk/13149

  22. Lucas Húngaro April 17, 2007 6:30 pm

    Valeu Thiago! Havia encontrado algo semelhante aqui uns minutos antes de você postar e me deparei com outro erro. Usei o que você postou (achei melhor do que o que eu havia encontrado, pois especifica mais níveis de isolamento).

    Porém, agora estou com outro erro…

    Faço um listAll() numa classe Cliente. Essa classe possui uma Collection com lazy loading. Para buscar os clientes dá tudo certo. Porém, quando tento iterar pela coleção de pedidos:


    Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.lecom.tecnologia.model.Cliente.pedidos, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
    at com.lecom.tecnologia.main.Tester.test(Tester.java:29)
    at com.lecom.tecnologia.main.Main.main(Main.java:17)

    Pelo jeito a sessão está sendo “perdida”. O logger me retorna algumas coisas relacionadas a isso (após selecionar os clientes com sucesso):


    DEBUG [main] (TransactionAspectSupport.java:305) - Completing transaction for [com.lecom.tecnologia.dao.IGenericDao.listAll]
    DEBUG [main] (AbstractPlatformTransactionManager.java:819) - Triggering beforeCommit synchronization
    DEBUG [main] (AbstractPlatformTransactionManager.java:832) - Triggering beforeCompletion synchronization
    DEBUG [main] (TransactionSynchronizationManager.java:190) - Removed value [org.springframework.orm.hibernate3.SessionHolder@3b4b1e] for key [org.hibernate.impl.SessionFactoryImpl@c0a9f9] from thread [main]
    DEBUG [main] (AbstractPlatformTransactionManager.java:845) - Triggering afterCommit synchronization
    DEBUG [main] (AbstractPlatformTransactionManager.java:861) - Triggering afterCompletion synchronization
    DEBUG [main] (SessionFactoryUtils.java:781) - Closing Hibernate Session
    DEBUG [main] (TransactionSynchronizationManager.java:272) - Clearing transaction synchronization

    Alguma idéia?

  23. Thiago April 17, 2007 6:58 pm

    Ai nesse caso, você tem que carregar a coleção de pedidos antecipadamente, pois quando você tenta acessa-la a sessão já foi fechada por isso da o lazy.

    Vai lá na documentação do hibernate e procura sobre fetch, você pode setar no seu mapeamento como default para sempre carregar a coleção, ou no metodo que estiver realizando a query, via criteria ou hql, especificar se deve carregar ou não.

  24. Lucas Húngaro April 17, 2007 7:40 pm

    Pois é, nas buscas que eu fiz encontrei isso mesmo. Ele fecha a sessão após cada transação, então ao tentar pegar a lista de pedidos vai dar erro pois já é outra sessão…

    A minha dúvida é: por esse motivo perco o benefício de desempenho que ganho com o lazy loading? Não há outro jeito a não ser fazer a query novamente utilizando left join fetch?

  25. Urubatan April 17, 2007 9:27 pm

    ùma solução para isto é se você estiver utilizando Hibernate sem o spring (o que parece por causa da factory que você mencionou) mudar na configuracão do hibernate para managed sessions, assim você cria e destroi as sessions.
    caso esteja utilizando o spring utilize algo parecido com isto:
    [java]
    SessionHolder sessionHolder =
    (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
    if(sessionHolder==null){
    TransactionSynchronizationManager.bindResource(getSessionFactory(),new SessionHolder(getSessionFactory().openSession());
    }[/java]

    não se esqueça que fazendo isto você é o responsável por fechar a sessão também …

  26. Urubatan April 17, 2007 9:28 pm

    PS.: eu achei muito legal outro visitante do blog responder uma duvida em um comentário :D Muito obrigado Thiago.

  27. Lucas Húngaro April 17, 2007 10:03 pm

    Muito legal a inciativa do Thiago mesmo.

    Urubatan, estou usando o Spring sim. É uma prática ruim usar uma DaoFactory com Spring?

    Não tenho o código agora, está no trabalho, mas fiz mais ou menos o seguinte:

    Uma interface genérica, semelhante a sua TOBaseDao.
    Uma classe abstrata com a implementação dessa interface para o hibernate, como a classe TOBaseHibernateDao.
    Uma interface genérica para a DaoFactory, com métodos como: public IClienteDao getClienteDao;
    Uma interface e implementação para cada Dao, onde posso colocar métodos específicos.

    A implementação da factory possui os atributos (as interfaces dos Daos) que são injetadas via método set pelo Spring.

    Nas classes que consomem os Daos, tenho apenas a interface da factory como atributo e a implementação é injetada pelo Spring.

    Obrigado pelo retorno, vou tentar isso no trabalho amanhã (trabalho da faculdade hoje =/ ).

    Sobre a minha segunda pergunta no primeiro post, alguma orientação? A mais óbvia que vejo seria colocar dentro de um Dao chamadas a outros, fazendo tudo na transação do primeiro, mas acho que isso não é muito bom…

  28. Lucas Húngaro April 18, 2007 9:02 am

    Como não quero ter que controlar a sessão, fiz o seguinte: antes de acessar a coleção de pedidos, uso o método clienteDao.rebind(cliente). Agora ele usa uma transação para buscar os clientes e depois uma transação para buscar cada lista de pedidos. Funciona, mas achei bem feio…

    De acordo com o que pesquisei, o padrão OpenSessionInView resolve isso, está correto?

  29. Urubatan April 18, 2007 9:51 am

    esta solução do rebind funciona também :D mas prende o teu código a api do Hibernate se isto não estiver sendo feito dentro de um DAO.
    se bem que não é exatamente um problema prender o código a API do Hibernate :D
    PS.: o OpenSessionInView também resolve isto …

  30. Lucas Húngaro April 18, 2007 2:22 pm

    Urubatan, como você costuma contornar essa situação? Ou você não utiliza lazy loading?

  31. Thiago April 18, 2007 3:42 pm

    Opa, vlw pessoal.

    Eu não custumo utilizar muito lazy loading, pelo menos no projeto no qual estou envolvido.
    Como utilizo ajax, via DWR, quando realizo as consultas geralmente trago tudo que eu quero, como o sistema não lida com grande volume de dados creio que não tem problemas, fora que realizo paginações para trazer uma quantidade limitada de dados.

  32. Urubatan April 18, 2007 4:19 pm

    Lucas, eu uso lazy bastante e como a maior parte das apps é web, o OpenSessionInView ja resolve o meu problema …
    quando trabalho com ajax procuro não utilizar as mesmas entidades (hoje estou fazendo isto e estou transformando em HashMaps os valores transferidos via ajax.

    e quando o OpenSessionInView não resolve, como esta semana que tive que implementar um wizard com a sessão aberta durante todo o wizard, eu copiei o OpenSessionInView filter do Spring, e fiz com que quando eu estivesse no wizard, ele armazenasse a session na HttpSession e usando um código parecido com:
    [java]
    SessionHolder sessionHolder =

    (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());

    if(sessionHolder==null){

    TransactionSynchronizationManager.bindResource(getSessionFactory(),new SessionHolder(getSessionFactory().openSession());

    }

    [/java]
    ele enquanto ainda no wizard, recuperasse a sessão do HttpSession e utilizasse a mesma durante todo o wizard :D
    mas como sempre, a solução mais apropriada, depende de cada situação :D

  33. Lucas Húngaro April 18, 2007 4:28 pm

    Legal… por enquanto estou apenas testando o Spring com Hibernate, então estou escrevendo uma aplicação console mesmo. Esse “esquema” do SessionHolder funcionou bem, apenas adicionei o “unbinding” antes de finalizar a aplicação:


    TransactionSynchronizationManager.unbindResource(this.sessionFactory);
    SessionFactoryUtils.releaseSession(session, this.sessionFactory);

    Estou fazendo uma aplicação também em .NET com NHibernate e lá costumo colocar a session no HttpSession também… funciona =D

    Alguma opinião sobre a minha implementação com factory? Estive pensando: seria bom eu configurar os beans dos Daos como lazy-init? Acho que seria uma boa, já que na factory eu tenho a injeção de todos os Daos, mas não vou utilizar todos sempre.

  34. Urubatan April 18, 2007 5:32 pm

    bom, sobre a factory …
    containers IoC foram criados para que ninguem mais utilizasse factories …
    por tanto, ou tu utiliza o spring ou a tua dao factory, não as duas coisas junto …

    mas esta é só a minha opinião :D

  35. Lucas Húngaro April 18, 2007 6:22 pm

    Sim, faz sentido… na verdade essa factory não tá criando nada, ela apenas retorna os daos que são injetados, então ela acaba perdendo a semântica de criadora, passando a ser apenas um objeto agregador, ou seja, acaba não sendo uma factory de verdade.

    Vi muita gente usando Spring e Castle Windsor (container IoC pra .NET) com essa “factory”, então acabei fazendo da mesma forma. Vou procurar saber mais sobre isso.

    Obrigado pela ajuda! :D

  36. Gessé July 10, 2007 11:10 am

    Olá Urubatan,

    Primeio gostaria de parabenizar pelo DAO genérico que vc construi. Desenvolvi um dao bem parecido com esse aí, só que o único problema aí é que tenho que criar uma classe dao concreta para todas as minhas classes persistíveis.

    Há alguma forma de isso não ser necessário?

  37. Urubatan July 10, 2007 3:49 pm

    é só alterar ele para passar o objectClass como parametro para o método que precisar dele :D

  38. Marcos Peron August 6, 2007 12:26 pm

    Olá,

    Muito bom seu artigo!!

    So fiquei com uma dúvida:

    E se eu quisesse que uma classe CurriculoDireito que estende Curriculo tivesse também um DAO que extendesse o DAO de Curriculo, como proceder?

    public interface CurriculoDAO extends TOBaseDao{
    public List getCurriculosByName();
    }

    Estou batendo a cabeça aqui mas não acho solução.

    public interface CurriculoDireitoDAO extends CurriculoDAO {
    // este deve ser implicito
    // public List getCurriculosByName();
    public List getCurriculoEstruturaDireito();
    }

    é uma sugestão meio tosca, mas o que eu gostaria era de poder Herdar os metodos das interfaces dos DAOs..

    Postei uma dúvida sobre isso no GUJ, e me direcionaram para seu blog :)
    http://www.guj.com.br/posts/list/66036.java

    se você tiver alguma idéia, seria muito grato.

    vlw

    Abraços e parabéns!

  39. Urubatan August 6, 2007 1:22 pm

    não entendi a dúvida …
    este DAO genérico não atrabalha em nada a utilização de herança …

  40. Maria sanches September 14, 2007 7:16 am

    para dar um exemplo de um blog

  41. Hewerton October 2, 2007 9:41 am

    Urubatan, poderia me explicar como funciona exatamente este método…
    public List findByExample(final T example, final int first, final int max)

  42. alexandre October 20, 2007 7:28 am

    Urubatan…
    esse “T” quer dizer o que mesmo ?que é um tipo indefinido ?

  43. Urubatan October 20, 2007 6:22 pm

    alexandre, isto é a sintaxe de generics do Java 5 :D

  44. Gilberto santos January 18, 2008 7:52 am

    ola urubatan.
    sobre sua primeira classe TOBaseDao
    certez

  45. Gilberto santos January 18, 2008 7:53 am

    ola urubatan.
    sobre sua primeira classe TOBaseDao
    bom, como ela implementa classe Generic sem receber o parametro

    TOBaseDao

    essa e minha duvida !
    abs.

  46. Alexandre April 13, 2008 10:03 am

    Algum exemplo sem utilizar spring? com struts 2

  47. Fabio May 18, 2008 3:07 pm

    Achei bem legal essa classe, muito útil também.
    Sobre os métodos para contar regitros, fico meio preocupado, pois caso a tabela seja muito grande, todos os registros serão carregados?
    Não teria como fazer uma verificação só da qtde, como faríamos com o SQL (select count(*) from tabela)?

    Valeu

Leave a comment

Please be polite and on topic. Your e-mail will never be published.