Este post faz parte de uma série sobre Spring, JPA e JSF. Caso algum
assunto abordado aqui não esteja claro, consulte este link: Spring + JPA.
Criar uma camada DAO (Data Access Objects) que possa ser reutilizada em outros projetos não é uma tarefa muito difícil, embora envolva vários conceitos de OOP (Object Oriented Programming) e Design Patterns.
Criar uma camada DAO (Data Access Objects) que possa ser reutilizada em outros projetos não é uma tarefa muito difícil, embora envolva vários conceitos de OOP (Object Oriented Programming) e Design Patterns.
Este exemplo mostrará uma construção que vai disponibilizar ao desenvolvedor um ambiente de CRUD (Create, Retrieve, Update, Delete) com algumas características interessantes:
- decisão automática por inserção ou atualização, baseada no valor da chave primária;
- recuperação por consulta total, personalizada ou nativa do banco de dados;
- exclusão direta ou por meio do sinalizador da classe Entidade (flagRemover);
- processamento de uma única entidade ou de uma lista de entidades, pertencentes a qualquer subclasse da classe Entidade.
A última característica é a mais interessante, pois possibilita enviar várias entidades diferentes de uma só vez, garantindo o processamento dentro da mesma transação, o que garante um rollback total em caso de erro.
Dentro de um pacote chamado de dao, vamos criar uma interface chamada InterfaceDAO. É muito importante a programação voltada a interfaces (ou classes abstratas, quando for interessante), pois traz ao projeto uma versatilidade muito grande, permitindo que sejam agregados outros mecanismos, sem interferir naquilo que já foi desenvolvido.
Segue o código da classe InterfaceDAO:
package dao; import java.io.Serializable; import java.util.List; public interface InterfaceDAO<T> { public void salvar(T entidade); public void salvarLista(List<T> lista); public T carregar(Class<T> classe, Serializable chavePrimaria); public List<T> listar(Class<T> classe); public List<T> consultaPersonalizada(String consulta); public List<T> consultaNativa(String consulta); }
Essa interface orienta o desenvolvedor a respeito dos métodos que serão necessários ao projeto e que podem ser utilizados em outras camadas, já que são métodos públicos. Não há método de atualização e exclusão na interface, pois a atualização depende apenas do valor da chave primária, e a exclusão, como foi visto anteriormente, será feita por meio da sinalização do atributo flagRemover. É importante observar que a interface não fixa o tipo das classes que serão processadas. Em vez disso, usa o tipo genérico, representado por T.
A seguir, a implementação da classe que o projeto utilizará para as operações CRUD:
A seguir, a implementação da classe que o projeto utilizará para as operações CRUD:
package dao; import entidades.Entidade; import java.io.Serializable; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.orm.jpa.support.SharedEntityManagerBean; import org.springframework.stereotype.Repository; @Repository("genericDAO") @Scope(value = "singleton") public class GenericDAO<T extends Entidade> implements InterfaceDAO<T> { @Autowired private SharedEntityManagerBean jpaTemplate; @Override public void salvar(T entidade) { if (entidade != null) { salvarSemFlush(entidade); jpaTemplate.getObject().flush(); } } private void salvarSemFlush(T entidade) { if (entidade != null) { try { if (entidade.getFlagRemover()) { if (entidade.getId() != null) { if (jpaTemplate.getObject().find(entidade.getClass(), entidade.getId()) != null) { jpaTemplate.getObject().remove(jpaTemplate.getObject().getReference(entidade.getClass(), entidade.getId())); } } } else { if (entidade.getId() == null) { jpaTemplate.getObject().persist(entidade); } else { if (jpaTemplate.getObject().find(entidade.getClass(), entidade.getId()) != null) { jpaTemplate.getObject().merge(entidade); } } } } catch (Exception e) { System.out.println(e.getLocalizedMessage());; } } } @Override public void salvarLista(List<T> lista) { Integer i = 0; if (lista != null) { for (T entidade : lista) { salvarSemFlush(entidade); i++; // sincroniza a cada 500 registros if ((i % 500) == 0) { try { jpaTemplate.getObject().flush(); } catch (Exception e) { System.out.println(e.getLocalizedMessage());; } } } // sincroniza os ultimos registros if (i % 500 != 0) { try { jpaTemplate.getObject().flush(); } catch (Exception e) { System.out.println(e.getLocalizedMessage());; } } } } @Override public T carregar(Class<T> classe, Serializable chave) { if (classe == null || chave == null) { return null; } return jpaTemplate.getObject().find(classe, chave); } @SuppressWarnings("unchecked") @Override public List<T> listar(Class<T> classe) { if (classe == null) { return null; } return jpaTemplate.getObject().createQuery("select a from " + classe.getSimpleName() + " a ").getResultList(); } @Override public List<T> consultaPersonalizada(String consulta) { if (consulta == null) { return null; } return jpaTemplate.getObject().createQuery(consulta).getResultList(); } @Override public List<T> consultaNativa(String consulta) { if (consulta == null) { return null; } return jpaTemplate.getObject().createNativeQuery(consulta).getResultList(); } public SharedEntityManagerBean getJpaTemplate() { return jpaTemplate; } }
Vamos à análise das linhas mais relevantes:
- linhas 11 e 12: configurações do Spring. Essa classe será injetada pelo Spring posteriormente, na camada de controle.
- linha 13:Essa classe restringe o uso às subclasses de Entidade e utiliza os métodos definidos em InterfaceDAO.
- linhas 15 e 16: modelo JPA injetado pelo Spring, e que foi definido em AppConfig (Configurando o Spring (II)).
- linhas 19 e 26: aqui a camada DAO possibilita ao desenvolvedor chamar o método salvar (para apenas uma entidade, com flush no final) ou chamar o método salvarLista (linha 51), que vai gerenciar o flush conforme o processamento vai atingindo blocos de 500 registros.
- demais linhas: implementação dos demais métodos.
No próximo post, a implementação de um serviço que faz o gerenciamento de transações para chamar os métodos DAO.
Nenhum comentário:
Postar um comentário