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