Implementando uma DAO Factory dinâmica.

Eu uso o design pattern DAO com a estratégia de fábrica abstrata desde que me entendo por gente.

Fiz a seguinte modificação na implementação demonstrada no catálogo de padrões J2EE:

  • Inicializar o objeto de conexão, com o repositório de dados, na inicialização da fábrica concreta.
  • Passar o objeto de conexão, com o repositório, pelo construtor das implementações(deste repositório) das interfaces DAOs.
  • Deslocar para o usuário, do DAO, a responsabilidade de criar e terminar uma transação ao executar seus métodos. Isto é feito à partir da DAOFactory, que possui métodos para controle transacional dos DAOs criados por ela.

Tenho usado essa implementação sem problemas há, aproximadamente, 2 anos.

Mas considero insuportável escrever os métodos abstratos(na fábrica abstrata) para retornar a implementação do DAO e ainda ter que escrever a implementação destes métodos em cada fábrica concreta. Implementação esta que consiste apenas em dar um new em uma classe e colocar o objeto de conexão com o repositório no construtor.

Neste feriado, eu resolvi dar um fim nesses métodos.

O desafio era fazer isso sem perder a checagem feita pelo compilador se a classe DAO que eu estou retornando implementa a interface DAO que eu estou querendo usar.

E para isso comecei definindo algumas convenções:

  • O nome da interface DAO será o nome da entidade com o sufixo DAO. Por exemplo, o DAO para a entidade Cliente será ClienteDAO;
  • O pacote, onde ficam as interfaces e a fábrica abstrata será assim: pacote.do.sistema.dao;
  • O nome da implementação da interface DAO será o nome da interface DAO com o prefixo do repositório. Por exemplo, a implementação usando JPA será: JpaClienteDAO;
  • O pacote, onde ficam a implementação e a fábrica concreta, será um sub-pacote, do pacote onde estão as interfaces e a fábrica abstrata, como em: pacote.do.sistema.dao.jpa;

Essas convenções me permitiram modificar a fábrica abstrata para retornar a implementação de uma interface DAO a partir da interface DAO.

Esta “mágica” é feita pelo método getDao:

public <T extends CrudDAO> T getDao(Class<T> daoInterface) thrws DAOException{

Mas ainda preciso saber o prefixo das implementações. Para resolver isso criei um método, na fábrica abstrata, que retorna uma String. Esta String é o prefixo da implementação, que a fábrica concreta, irá informar.

Na fábrica abstrata, isto é, a classe DAOFactory:

protected abstract String getPrefixoImpl();

E a implementação na fábrica concreta usando a JPA, isto é, JpaDAOFactory:

@Override
protected String getPrefixoImpl() {
return "jpa";
}

 

Eu tenho uma classe base para os meus DAOs, que implementam as operações básicas de inclusão, alteração, exclusão e busca da entidade, e tem um contrutor que recebe o EntityManager a ser usado nestas operações.
Por conta deste contrutor eu preciso dos métodos getRepositoryTypes() e o getRepositoryArgs que irão retornar o objeto responsável pelo acesso ao banco de dados(EntityManager no caso do JPA, Session no caso de Hibernate e Connection no caso de JDBC “cru”).

Com essas alterações simples eu posso recuperar a implementação do DAO sem precisar criar um método para cada DAO em cada implementação da fábrica abstrata.

E para usar a nova implementação, o código fica assim:

DAOFactory factory = DAOFactory.getInstance();
EntidadeDAO dao = factory.getDao(EntidadeDAO.class);

Faça o download do projeto, para Eclipse, que tem a implementação de tudo o que eu escrevi até aqui.

Por restrições do WordPress eu tive que renomear a extensão do arquivo para “pdf”, basta trocar por “zip” que você irá conseguir descompactá-lo.

Para usá-lo:

  • Importe o projeto para o seu eclipse;
  • Coloque o driver para o banco de dados e adicione-o ao class-path do projeto;
  • Configure o arquivo persistence.xml na pasta META-INF com os dados da conexão ao seu banco;
  • Execute a classe ExemploMain.

Sugestões serão bem vindas. E analisadas, caso eu concorde coloco no exemplo e atualizo ele.

Po-por hoje é só pe-pe-ssoal. =D

Anúncios

15 opiniões sobre “Implementando uma DAO Factory dinâmica.

  1. Opa,

    estou implementando a sua fabrica abstrada de JPA (que por sinal é muito interessante), e seugui uma duvida.

    quado eum precisar fazer um query (por named query). o que eu fiz, foi:
    1- crigar um get/setter do manager na classe JpaBaseDAO.

    depois na minha classe entity onde estão as @NamedQuety criei o metodo

    @SuppressWarnings(“unchecked”)
    public static List findByGui(Integer oid){
    JpaDAOFactory factory = (JpaDAOFactory) DAOFactory.getInstance(DAOFactory.JPA);
    Query q = factory.getManager().createNamedQuery (“selectWhereGui”);
    q.setParameter (“gui”, oid);
    return q.getResultList();
    }

    o que voce acha dessa abordagem?

  2. 1. Não precisa dos métodos get e set para o EntityManager, porque ele pode ser acessado diretamente no DAO. O nome do atributo é manager.

    2. na sua entidade você pode continuar usando:
    public static List findByGui(Integer oid){
    DAOFactory factory = DAOFactory.getInstance();
    SuaEntidadeDAO dao = factory.getDao(SuaEntidadeDAO.class);

    return dao.findByGui(oid);
    }

    E no DAO, você usa a NamedQuery:

    public List findByGui(oid){
    Query query = manager.createNamedQuery(“selectWhereGui”);
    q.setParameter (”gui”, oid);

    return q.getResultList();
    }

    [],
    AC

  3. Pingback: Data Access Object (DAO) « Luciano Silva

  4. O que me incomodou no seu exemplo é o controle de transação ser feito pelo DAO. Por exemplo se uma transação envolver mais de um DAO, em qual deles eu mando fechar a transação? Entendo que em qualquer um serve, mas não fica claro isso no código.

    Nos métodos findById e findAll, você está passando o Class. Uma vez que os DAOs possuem uma implementação, poderia usar a idéia de TemplateMethod e criar um método protected abstrato que retornasse o Class.

    Gostei muito do uso da API de Criteria e do método de paginação. Inclusive devo fazer um update do meu exemplo usando a mesma idéia. 🙂

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s