DAO E PERSISTÊNCIA DE DADOS
A persistência refere-se ao armazenamento não-volátil de dados.
O padrão DAO (Data Access Object) cria uma camada intermediária entre a camada de negócios e os detalhes de armazenamento persistente.
O principal objectivo de um DAO é encapsular o acesso e a manipulação de dados numa camada separada.
A intenção da existência dos DAOS é que eles não possuam nenhuma lógica de negócio.
Geralmente, cria-se um DAO para cada objeto do domínio do sistema, ou então para cada módulo, ou conjunto de entidades fortemente relacionadas e cada DAO oferece, fundamentalmente, operações CRUD para cada objeto persistente do domínio.
Numa implementação mais acaba, cada DAO possui uma interface, que especifica os métodos de manipulação de dados e em não poucos casos, um DAO genérico de onde herdam os demais DAOs.
O DAO esconde todos os detalhes de implementação do acesso à fonte de dados, bem como as operações de persistência e busca.
DAOs da aplicação
Na aplicação em desenvolvimento foi criada um interface genérica, GenericoDAO, onde são definidos os comportamentos comuns a todos os DAOs da aplicação e todos os DAOs implementarão esta interface.
Logo a seguir encontra-se o código de dois DAOs que podem servir de referencia para a construção dos demais.
Nestes além dos métodos do CRUD tradicional foi implementado um método privado, popularComDados(Projecto projecto, ResultSet rs), cuja responsabilidade é carregar os dados da entidade. Este metodo é utilizado em todos os métodos com responsabilidade de fazer buscas e listagem.
Interface GenericoDAO.java
package org.ao.projecto.dao;
import java.util.List;
public interface GenericoDAO<T> {
void save(T t);
void update(T t);
void delete(T t);
T findById(Long id);
List<T> findAll();
}
Classe ProjetoDAO.java
...
public class ProjetoDAO implements GenericoDAO<Projeto> {
private static final String INSERIR = "INSERT INTO projeto(codigo_projeto, nome_projeto, descricao_projeto, custo_projeto, entidade_financiadora, id_tipo_projeto) VALUES (?, ?, ?, ?, ?, ?)";
private static final String ACTUALIZAR = "UPDATE projeto SET codigo_projeto = ?, nome_projeto = ?, descricao_projeto = ?, custo_projeto = ?, entidade_financiadora = ?, id_tipo_projeto = ? WHERE id_projeto = ?";
private static final String ELIMINAR = "DELETE FROM projeto WHERE id_projeto = ?";
private static final String BUSCAR_POR_CODIGO = "SELECT p.id_projeto, p.codigo_projeto, p.nome_projeto, p.descricao_projeto, p.custo_projeto, p.entidade_financiadora, t.nome_tipo_projeto FROM projeto p INNER JOIN tipo_projeto t ON p.id_tipo_projeto = t.id_tipo_projeto WHERE p.id_projeto = ?";
private static final String LISTAR_TUDO = "SELECT p.id_projeto, p.codigo_projeto, p.nome_projeto, p.descricao_projeto, p.custo_projeto, p.entidade_financiadora, t.nome_tipo_projeto FROM projeto p INNER JOIN tipo_projeto t ON p.id_tipo_projeto = t.id_tipo_projeto";
public ProjetoDAO() {
}
@Override
public void save(Projeto projeto) {
PreparedStatement ps = null;
Connection conn = null;
if (projeto == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(INSERIR);
ps.setString(1, projeto.getCodigoProjeto());
ps.setString(2, projeto.getNomeProjeto());
ps.setString(3, projeto.getDescricaoProjeto());
ps.setDouble(4, projeto.getCustoProjeto());
ps.setString(5, projeto.getEntidadeFinanciadora());
ps.setInt(6, projeto.getTipoProjeto().getIdTipoProjeto());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao inserir dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public void update(Projeto projeto) {
PreparedStatement ps = null;
Connection conn = null;
if (projeto == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(ACTUALIZAR);
ps.setString(1, projeto.getCodigoProjeto());
ps.setString(2, projeto.getNomeProjeto());
ps.setString(3, projeto.getDescricaoProjeto());
ps.setDouble(4, projeto.getCustoProjeto());
ps.setString(5, projeto.getEntidadeFinanciadora());
ps.setInt(6, projeto.getTipoProjeto().getIdTipoProjeto());
ps.setInt(7, projeto.getIdProjeto());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao actualizar dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public void delete(Projeto projeto) {
PreparedStatement ps = null;
Connection conn = null;
if (projeto == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(ELIMINAR);
ps.setInt(1, projeto.getIdProjeto());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao eliminar dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public Projeto findById(Integer id) {
PreparedStatement ps = null;
Connection conn = null;
ResultSet rs = null;
Projeto projeto = new Projeto();
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(BUSCAR_POR_CODIGO);
ps.setInt(1, id);
rs = ps.executeQuery();
if (!rs.next()) {
System.err.println("Não foi encontrado nenhum registo com o id: " + id);
}
popularComDados(projeto, rs);
} catch (SQLException ex) {
System.err.println("Erro ao ler dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps, rs);
}
return projeto;
}
@Override
public List<Projeto> findAll() {
PreparedStatement ps = null;
Connection conn = null;
ResultSet rs = null;
List<Projeto> projetos = new ArrayList<>();
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(LISTAR_TUDO);
rs = ps.executeQuery();
while (rs.next()) {
Projeto projeto = new Projeto();
popularComDados(projeto, rs);
projetos.add(projeto);
}
} catch (SQLException ex) {
System.err.println("Erro ao ler dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn);
}
return projetos;
}
private void popularComDados(Projeto projeto, ResultSet rs) {
try {
projeto.setIdProjeto(rs.getInt("p.id_projeto"));
projeto.setCodigoProjeto(rs.getString("p.codigo_projeto"));
projeto.setNomeProjeto(rs.getString("p.nome_projeto"));
projeto.setDescricaoProjeto(rs.getString("p.descricao_projeto"));
projeto.setCustoProjeto(rs.getDouble("p.custo_projeto"));
projeto.setEntidadeFinanciadora(rs.getString("p.entidade_financiadora"));
TipoProjeto tipoProjecto = new TipoProjeto();
tipoProjecto.setNomeTipoProjeto(rs.getString("t.nome_tipo_projeto"));
projeto.setTipoProjeto(tipoProjecto);
} catch (SQLException ex) {
System.err.println("Erro ao carregar dados: " + ex.getLocalizedMessage());
}
}
}
ColocacaoDAO.java
...
public class ColocacaoDAO implements GenericoDAO<Colocacao> {
private static final String INSERIR = "INSERT INTO colocacao (id_funcionario, id_projeto, data_inicio, data_fim) VALUES (?, ?, ?, ?)";
private static final String ACTUALIZAR = "UPDATE colocacao SET id_funcionario =?, id_projeto=?, data_inicio =?, data_fim=? WHERE id_colocacao =?";
private static final String ELIMINAR = "DELETE FROM colocacao WHERE id_colocacao =?";
private static final String BUSCAR_POR_CODIGO = " SELECT c.id_colocacao, f.nome_funcionario, f.sobrenome_funcionario, p.codigo_projeto, p.nome_projeto, c.data_inicio, c.data_fim FROM colocacao c INNER JOIN funcionario f ON c.id_funcionario = f.id_funcionario INNER JOIN projeto p ON c.id_projeto = p.id_projeto WHERE id_colocacao = ?";
private static final String LISTAR_TUDO = " SELECT c.id_colocacao, f.nome_funcionario, f.sobrenome_funcionario, p.codigo_projeto, p.nome_projeto, c.data_inicio, c.data_fim FROM colocacao c INNER JOIN funcionario f ON c.id_funcionario = f.id_funcionario INNER JOIN projeto p ON c.id_projeto = p.id_projeto";
public ColocacaoDAO() {
}
@Override
public void save(Colocacao colocacao) {
PreparedStatement ps = null;
Connection conn = null;
if (colocacao == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(INSERIR);
ps.setInt(1, colocacao.getFuncionario().getIdFuncionario());
ps.setInt(2, colocacao.getProjecto().getIdProjeto());
ps.setDate(3, new java.sql.Date(colocacao.getDataInicio().getTime()));
ps.setDate(4, new java.sql.Date(colocacao.getDataFim().getTime()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao inserir dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public void update(Colocacao colocacao) {
PreparedStatement ps = null;
Connection conn = null;
if (colocacao == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(ACTUALIZAR);
ps.setInt(1, colocacao.getFuncionario().getIdFuncionario());
ps.setInt(2, colocacao.getProjecto().getIdProjeto());
ps.setDate(3, new java.sql.Date(colocacao.getDataInicio().getTime()));
ps.setDate(4, new java.sql.Date(colocacao.getDataFim().getTime()));
ps.setInt(5, colocacao.getIdColocacao());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao actualizar dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public void delete(Colocacao colocacao) {
PreparedStatement ps = null;
Connection conn = null;
if (colocacao == null) {
System.err.println("O valor passado nao pode ser nulo");
}
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(ELIMINAR);
ps.setInt(1, colocacao.getIdColocacao());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("Erro ao eliminar dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps);
}
}
@Override
public Colocacao findById(Integer id) {
PreparedStatement ps = null;
Connection conn = null;
ResultSet rs = null;
Projeto projeto = new Projeto();
Colocacao colocacao = new Colocacao();
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(BUSCAR_POR_CODIGO);
ps.setInt(1, id);
rs = ps.executeQuery();
if (!rs.next()) {
System.err.println("Não foi encontrado nenhum registo com o id: " + id);
}
popularComDados(colocacao, rs);
} catch (SQLException ex) {
System.err.println("Erro ao ler dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn, ps, rs);
}
return colocacao;
}
@Override
public List<Colocacao> findAll() {
PreparedStatement ps = null;
Connection conn = null;
ResultSet rs = null;
List<Colocacao> colocacaos = new ArrayList<>();
try {
conn = Conexao.getConnection();
ps = conn.prepareStatement(LISTAR_TUDO);
rs = ps.executeQuery();
while (rs.next()) {
Colocacao colocacao = new Colocacao();
popularComDados(colocacao, rs);
colocacaos.add(colocacao);
}
} catch (SQLException ex) {
System.err.println("Erro ao ler dados: " + ex.getLocalizedMessage());
} finally {
Conexao.closeConnection(conn);
}
return colocacaos;
}
private void popularComDados(Colocacao colocacao, ResultSet rs) {
try {
colocacao.setIdColocacao(rs.getInt("c.id_colocacao"));
Funcionario funcionario = new Funcionario();
funcionario.setNomeFuncionario(rs.getString("f.nome_funcionario"));
funcionario.setSobrenomeFuncionario(rs.getString("f.sobrenome_funcionario"));
colocacao.setFuncionario(funcionario);
Projeto projeto = new Projeto();
projeto.setCodigoProjeto(rs.getString("p.codigo_projeto"));
projeto.setNomeProjeto(rs.getString("p.nome_projeto"));
colocacao.setProjecto(projeto);
colocacao.setDataInicio(rs.getDate("c.data_inicio"));
colocacao.setDataFim(rs.getDate("c.data_fim"));
} catch (SQLException ex) {
System.err.println("Erro ao carregar dados: " + ex.getLocalizedMessage());
}
}
}
Pratica
Os DAOs apresentados contem elementos comuns aos demais DAOs. Para efeitos de pratica e treinamento recomenda-se ao leitor a implementação dos demais DAOs da aplicação tendo como referencia os exemplos anteriores.