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