- Cenário de exemlo
- Tabelas da base de dados
- Classes de dados
- Classe da fábrica de conexões
- Classes DAO
Cenário de exemlo
Vamos criar a camada de acesso a dados para um simples cadastro de funcionários com dependentes, conforme ilustração.
Tabelas da base de dados
Nesse cenário teremos apenas duas tabelas, Funcionarios e Dependentes com um relacionamento de um funcionário para zero ou mais dependentes.
Isto é, eu posso ter um funcionário sem nenhum dependente, com apenas um dependente ou mesmo com 20 dependentes. Mas cada dependente só poderá ter apenas um funcionário.
Assim, sendo, teremos as seguintes tabelas:
CREATE TABLE Funcionarios (
id INT IDENTITY PRIMARY KEY,
nome VARCHAR(50) NOT NULL,
cpf VARCHAR(11) NOT NULL,
nascimento DATE NOT NULL,
salario FLOAT NOT NULL
);
CREATE TABLE Dependentes (
id INT IDENTITY PRIMARY KEY,
nome VARCHAR(50) NOT NULL,
nascimento DATE NOT NULL,
funcionario_id INT NOT NULL REFERENCES Funcionarios(id)
);
Classes de dados
Para poder receber os dados, vamos criar classes POJO para cada tabela:
package fanese.web.model;
import java.util.Date;
public class Funcionario {
private int id;
private String nome;
private String cpf;
private Date nascimento;
private double salario;
// getters e setters
...
}
package fanese.web.model;
import java.util.Date;
public class Dependente {
private int id;
private String nome;
private Date nascimento;
private int funcionarioId;
// getters e setters
...
}
Classe da fábrica de conexões
As classes DAO não precisam saber de informações de conexão ao SGBD, isto fica na classe de fábrica de conexões.
Note que a classe da fábrica fica no subpacote dao
:
package fanese.web.dao;
import org.sql2o.Sql2o;
public class Database extends Sql2o {
/**
* Constantes das informações de conexão ao SGBD
*/
private static final String
JDBC_URL = "jdbc:sqlserver://localhost;databaseName=PROGWEB",
USER = "sa",
PASSWORD = "123456";
//<editor-fold desc="Instância única da classe (padrão singleton)">
private Database() {
super(JDBC_URL, USER, PASSWORD);
}
private static final Database INSTANCE = new Database();
public static Database getInstance() {
return INSTANCE;
}
//</editor-fold>
}
Classes DAO
Segue abaixo as classes de acesso a dados desse cenário de exemplo.
FuncionarioDao
package fanese.web.dao;
import fanese.web.model.Dependente;
import fanese.web.model.Funcionario;
import org.sql2o.Connection;
import java.util.List;
public class FuncionarioDao {
/**
* Referência da fábrica de conexões
*/
private static final Database db = Database.getInstance();
public Funcionario obter(int id) {
String query =
"SELECT id, nome, cpf, nascimento, salario " +
"FROM Funcionarios " +
"WHERE id = :id";
try (Connection con = db.open()) {
return con.createQuery(query)
.addParameter("id", id)
.executeAndFetchFirst(Funcionario.class);
}
}
public List<Funcionario> obterTodos() {
String query =
"SELECT id, nome, cpf, nascimento, salario " +
"FROM Funcionarios";
try (Connection con = db.open()) {
return con.createQuery(query)
.executeAndFetch(Funcionario.class);
}
}
public boolean adicionar(Funcionario f) {
String query =
"INSERT INTO Funcionarios (nome, cpf, nascimento, salario) " +
"VALUES (:nome, :cpf, :nascimento, :salario)";
try (Connection con = db.open()) {
con.createQuery(query)
.addParameter("nome", f.getNome())
.addParameter("cpf", f.getCpf())
.addParameter("nascimento", f.getNascimento())
.addParameter("salario", f.getSalario())
.executeUpdate();
// Obtém id gerado automaticamente pelo SGBD
Integer id = con.getKey(Integer.class);
f.setId(id);
return con.getResult() > 0;
}
}
public boolean modificar(Funcionario f) {
String query =
"UPDATE Funcionarios " +
"SET nome = :nome, cpf = :cpf, nascimento = :nascimento, salario = :salario " +
"WHERE id = :id";
try (Connection con = db.open()) {
con.createQuery(query)
.addParameter("id", f.getId())
.addParameter("nome", f.getNome())
.addParameter("cpf", f.getCpf())
.addParameter("nascimento", f.getNascimento())
.addParameter("salario", f.getSalario())
.executeUpdate();
return con.getResult() > 0;
}
}
public boolean excluir(Funcionario f) {
// Abre transação em vez de conexão normal
try (Connection con = db.beginTransaction()) {
// Exclui todos os dependentes do funcionário
con.createQuery("DELETE Dependentes WHERE funcionario_id = :id")
.addParameter("id", f.getId())
.executeUpdate();
// Depois remove o funcionário
con.createQuery("DELETE Funcionarios WHERE id = :id")
.addParameter("id", f.getId())
.executeUpdate();
int result = con.getResult();
// Valida a transação
con.commit();
return result > 0;
}
}
public List<Dependente> obterDependentes(Funcionario f) {
String query =
"SELECT id, nome, nascimento, funcionario_id " +
"FROM Dependentes " +
"WHERE funcionario_id = :id";
try (Connection con = db.open()) {
return con.createQuery(query)
.addParameter("id", f.getId())
.executeAndFetch(Dependente.class);
}
}
public boolean adicionarDependente(Funcionario f, Dependente dep) {
// Define o relacionamento
dep.setFuncionarioId(f.getId());
// Reaproveita o DAO já existente
DependenteDao dependenteDao = new DependenteDao();
return dependenteDao.adicionar(dep);
}
public boolean excluirDependente(Funcionario f, Dependente dep) {
// Verifica o relacionamento
if (f.getId() != dep.getFuncionarioId()) {
return false;
}
// Reaproveita o DAO já existente
DependenteDao dependenteDao = new DependenteDao();
return dependenteDao.excluir(dep);
}
}
DependenteDao
package fanese.web.dao;
import fanese.web.model.Dependente;
import fanese.web.model.Funcionario;
import org.sql2o.Connection;
import java.util.List;
public class DependenteDao {
/**
* Referência da fábrica de conexões
*/
private static final Database db = Database.getInstance();
public Dependente obter(int id) {
String query =
"SELECT id, nome, nascimento, funcionario_id " +
"FROM Dependentes " +
"WHERE id = :id";
try (Connection con = db.open()) {
return con.createQuery(query)
.addParameter("id", id)
.executeAndFetchFirst(Dependente.class);
}
}
public List<Dependente> obterTodos() {
String query =
"SELECT id, nome, nascimento, funcionario_id " +
"FROM Dependentes";
try (Connection con = db.open()) {
return con.createQuery(query)
.executeAndFetch(Dependente.class);
}
}
public boolean adicionar(Dependente dep) {
String query =
"INSERT INTO Dependentes (nome, nascimento, funcionario_id) " +
"VALUES (:nome, :nascimento, :funcionario_id)";
try (Connection con = db.open()) {
con.createQuery(query)
.addParameter("nome", dep.getNome())
.addParameter("nascimento", dep.getNascimento())
.executeUpdate();
// Obtém id gerado automaticamente pelo SGBD
Integer id = con.getKey(Integer.class);
dep.setId(id);
return con.getResult() > 0;
}
}
public boolean modificar(Dependente dep) {
String query =
"UPDATE Dependentes " +
"SET nome = :nome, nascimento = :nascimento " +
"WHERE id = :id";
try (Connection con = db.open()) {
con.createQuery(query)
.addParameter("id", dep.getId())
.addParameter("nome", dep.getNome())
.addParameter("nascimento", dep.getNascimento())
.executeUpdate();
return con.getResult() > 0;
}
}
public boolean excluir(Dependente dep) {
String query =
"DELETE Dependentes WHERE id = :id";
try (Connection con = db.open()) {
con.createQuery(query)
.addParameter("id", dep.getId())
.executeUpdate();
return con.getResult() > 0;
}
}
public Funcionario obterFuncionario(Dependente dep) {
// Reaproveita o DAO já existente
FuncionarioDao funcionarioDao = new FuncionarioDao();
return funcionarioDao.obter(dep.getFuncionarioId());
}
}