CREATE TABLE usuarios (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE,
senha VARCHAR(255),
data_cadastro TIMESTAMP DEFAULT NOW()
);
public class Pessoa implements Serializable {
private int id;
private String nome;
private String email;
// Construtor sem argumentos
public Pessoa() {
}
// Getters e Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public interface PessoaDAO {
// Create
public void inserir(Pessoa pessoa) throws SQLException;
// Read
public Pessoa buscarPorId(int id) throws SQLException;
public List listarTodos() throws SQLException;
// Update
public void atualizar(Pessoa pessoa) throws SQLException;
// Delete
public void excluir(int id) throws SQLException;
}
public void inserir(Pessoa pessoa) throws SQLException {
// SQL com placeholders para evitar SQL Injection
String sql = "INSERT INTO pessoas (nome, email) VALUES (?, ?)";
// Try-with-resources garante fechamento dos recursos
try (
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS)
) {
// Substituição dos placeholders por valores reais
stmt.setString(1, pessoa.getNome());
stmt.setString(2, pessoa.getEmail());
// Executa a inserção e retorna número de linhas afetadas
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Falha ao inserir, nenhuma linha afetada.");
}
// Recupera o ID gerado pelo banco
try (ResultSet generatedKeys = stmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
pessoa.setId(generatedKeys.getInt(1));
}
}
}
}
public Pessoa buscarPorId(int id) throws SQLException {
String sql = "SELECT id, nome, email FROM pessoas WHERE id = ?";
try (
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)
) {
stmt.setInt(1, id);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
Pessoa pessoa = new Pessoa();
pessoa.setId(rs.getInt("id"));
pessoa.setNome(rs.getString("nome"));
pessoa.setEmail(rs.getString("email"));
return pessoa;
} else {
return null; // Nenhuma pessoa encontrada com o ID
}
}
}
}
public List listarTodos() throws SQLException {
String sql = "SELECT id, nome, email FROM pessoas";
List pessoas = new ArrayList<>();
try (
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()
) {
while (rs.next()) {
Pessoa pessoa = new Pessoa();
pessoa.setId(rs.getInt("id"));
pessoa.setNome(rs.getString("nome"));
pessoa.setEmail(rs.getString("email"));
pessoas.add(pessoa);
}
}
return pessoas;
}
public void atualizar(Pessoa pessoa) throws SQLException {
String sql = "UPDATE pessoas SET nome = ?, email = ? WHERE id = ?";
try (
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)
) {
// Configurando autocommit como false para controle de transação
conn.setAutoCommit(false);
try {
stmt.setString(1, pessoa.getNome());
stmt.setString(2, pessoa.getEmail());
stmt.setInt(3, pessoa.getId());
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Falha ao atualizar, nenhuma linha afetada.");
}
// Confirma a transação
conn.commit();
} catch (Exception e) {
// Desfaz alterações em caso de erro
conn.rollback();
throw e;
} finally {
// Restaura configuração padrão
conn.setAutoCommit(true);
}
}
}
public void excluir(int id) throws SQLException {
String sql = "DELETE FROM pessoas WHERE id = ?";
try (
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)
) {
stmt.setInt(1, id);
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Falha ao excluir, registro não encontrado.");
}
} catch (SQLIntegrityConstraintViolationException e) {
// Tratamento específico para violações de integridade
throw new SQLException("Não é possível excluir. " +
"Este registro possui dependências em outras tabelas.", e);
}
}
<%@ page import="java.util.List" %>
<%@ page import="dao.CategoriaDAO" %>
<%@ page import="model.Categoria" %>
<%
CategoriaDAO categoriaDAO = new CategoriaDAO();
List<Categoria> categorias = categoriaDAO.listarTodos();
%>
<select name="categoria" id="categoria" class="form-control">
<option value="">Selecione uma categoria</option>
<% for(Categoria cat : categorias) { %>
<option value="<%= cat.getId() %>">
<%= cat.getNome() %>
</option>
<% } %>
</select>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- Configurando atributos no servlet -->
<!-- request.setAttribute("produtos", produtoDAO.listarTodos()); -->
<select name="produto">
<c:forEach items="${produtos}" var="produto">
<option value="${produto.id}">${produto.nome} -
R$ ${produto.preco}</option>
</c:forEach>
</select>
<%
List<Estado> estados = estadoDAO.listarTodos();
String estadoSelecionado = request.getParameter("estado");
%>
<select name="estado" id="estado">
<% for(Estado estado : estados) { %>
<option value="<%= estado.getUf() %>"
<%= estado.getUf().equals(estadoSelecionado) ?
"selected" : "" %>>
<%= estado.getNome() %>
</option>
<% } %>
</select>
<input type="email" name="email"
required
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
title="Digite um email válido">
<input type="tel" name="telefone"
required
pattern="[0-9]{10,11}"
title="Digite apenas números (DDD + número)">
// Em um servlet ou controller
String email = request.getParameter("email");
String nome = request.getParameter("nome");
String cpf = request.getParameter("cpf");
List<String> erros = new ArrayList<>();
if (email == null || email.trim().isEmpty()) {
erros.add("Email é obrigatório");
} else if (!email.matches("[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$")) {
erros.add("Email inválido");
}
if (nome == null || nome.trim().length() < 3) {
erros.add("Nome deve ter pelo menos 3 caracteres");
}
if (cpf == null || !validarCPF(cpf)) {
erros.add("CPF inválido");
}
if (!erros.isEmpty()) {
request.setAttribute("erros", erros);
request.getRequestDispatcher("/formulario.jsp").forward(request, response);
return;
}
<c:if test="${not empty erros}">
<div class="alert alert-danger">
<ul>
<c:forEach items="${erros}" var="erro">
<li>${erro}</li>
</c:forEach>
</ul>
</div>
</c:if>
<c:if test="${not empty sucesso}">
<div class="alert alert-success">
${sucesso}
</div>
</c:if>
<script>
function toggleFields() {
var tipoPessoa = document.getElementById("tipoPessoa").value;
if (tipoPessoa === "PF") {
document.getElementById("camposCPF").style.display = "block";
document.getElementById("camposCNPJ").style.display = "none";
} else if (tipoPessoa === "PJ") {
document.getElementById("camposCPF").style.display = "none";
document.getElementById("camposCNPJ").style.display = "block";
}
}
</script>
<select id="tipoPessoa" name="tipoPessoa" onchange="toggleFields()">
<option value="PF">Pessoa Física</option>
<option value="PJ">Pessoa Jurídica</option>
</select>
<div id="camposCPF">
<label for="cpf">CPF:</label>
<input type="text" id="cpf" name="cpf">
</div>
<div id="camposCNPJ" style="display:none">
<label for="cnpj">CNPJ:</label>
<input type="text" id="cnpj" name="cnpj">
</div>
<c:choose>
<c:when test="${usuario.tipo == 'ADMIN'}">
<!-- Campos específicos para administradores -->
<div class="form-group">
<label for="nivelAcesso">Nível de Acesso:</label>
<select name="nivelAcesso">
<option value="1">Básico</option>
<option value="2">Intermediário</option>
<option value="3">Total</option>
</select>
</div>
</c:when>
<c:when test="${usuario.tipo == 'CLIENTE'}">
<!-- Campos específicos para clientes -->
<div class="form-group">
<label for="interesses">Interesses:</label>
<input type="text" name="interesses">
</div>
</c:when>
</c:choose>
<form action="PessoaServlet" method="post">
<input type="hidden" name="id" value="${pessoa.id}">
<div class="form-group">
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome"
value="${pessoa.nome}" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email"
value="${pessoa.email}" required>
</div>
<button type="submit">Salvar</button>
</form>
@WebServlet("/PessoaServlet")
public class PessoaServlet extends HttpServlet {
private PessoaDAO pessoaDAO = new PessoaDAOImpl();
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
try {
// Recupera parâmetros do formulário
String idStr = request.getParameter("id");
String nome = request.getParameter("nome");
String email = request.getParameter("email");
// Cria e preenche o bean
Pessoa pessoa = new Pessoa();
if (idStr != null && !idStr.isEmpty()) {
pessoa.setId(Integer.parseInt(idStr));
}
pessoa.setNome(nome);
pessoa.setEmail(email);
// Decide entre inserir ou atualizar
if (pessoa.getId() == 0) {
pessoaDAO.inserir(pessoa);
request.setAttribute("mensagem",
"Pessoa inserida com sucesso!");
} else {
pessoaDAO.atualizar(pessoa);
request.setAttribute("mensagem",
"Pessoa atualizada com sucesso!");
}
} catch (Exception e) {
request.setAttribute("erro",
"Erro: " + e.getMessage());
}
request.getRequestDispatcher("/pessoas.jsp")
.forward(request, response);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cadastro de Produto</title>
</head>
<body>
<h1>Cadastro de Produto</h1>
<c:if test="${not empty mensagem}">
<div>${mensagem}</div>
</c:if>
<form action="ProdutoServlet" method="post">
<input type="hidden" name="id" value="${produto.id}">
<div>
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome" value="${produto.nome}" required>
</div>
<div>
<label for="preco">Preço:</label>
<input type="number" id="preco" name="preco" step="0.01" value="${produto.preco}" required>
</div>
<div>
<label for="categoria">Categoria:</label>
<select id="categoria" name="categoriaId" required>
<option value="">Selecione...</option>
<c:forEach items="${categorias}" var="categoria">
<option value="${categoria.id}"
<c:if test="${categoria.id == produto.categoria.id}">selected</c:if>>
${categoria.nome}
</option>
</c:forEach>
</select>
</div>
<button type="submit">Salvar</button>
</form>
<h2>Produtos Cadastrados</h2>
<table border="1">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Preço</th>
<th>Categoria</th>
<th>Ações</th>
</tr>
<c:forEach items="${produtos}" var="prod">
<tr>
<td>${prod.id}</td>
<td>${prod.nome}</td>
<td>R$ ${prod.preco}</td>
<td>${prod.categoria.nome}</td>
<td>
<a href="ProdutoServlet?acao=editar&id=${prod.id}">Editar</a>
<a href="ProdutoServlet?acao=excluir&id=${prod.id}"
onclick="return confirm('Confirma exclusão?')">Excluir</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
@WebServlet("/ProdutoServlet")
public class ProdutoServlet extends HttpServlet {
private ProdutoDAO produtoDAO = new ProdutoDAOImpl();
private CategoriaDAO categoriaDAO = new CategoriaDAOImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String acao = request.getParameter("acao");
try {
if ("editar".equals(acao)) {
int id = Integer.parseInt(request.getParameter("id"));
Produto produto = produtoDAO.buscarPorId(id);
request.setAttribute("produto", produto);
} else if ("excluir".equals(acao)) {
int id = Integer.parseInt(request.getParameter("id"));
produtoDAO.excluir(id);
request.setAttribute("mensagem", "Produto excluído com sucesso!");
}
request.setAttribute("categorias", categoriaDAO.listarTodos());
request.setAttribute("produtos", produtoDAO.listarTodos());
} catch (Exception e) {
request.setAttribute("erro", "Erro: " + e.getMessage());
}
request.getRequestDispatcher("/produtos.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// Recupera parâmetros
String idStr = request.getParameter("id");
String nome = request.getParameter("nome");
String precoStr = request.getParameter("preco");
String categoriaIdStr = request.getParameter("categoriaId");
// Converte e valida
double preco = Double.parseDouble(precoStr);
int categoriaId = Integer.parseInt(categoriaIdStr);
// Busca categoria
Categoria categoria = categoriaDAO.buscarPorId(categoriaId);
// Cria produto
Produto produto = new Produto();
if (idStr != null && !idStr.isEmpty()) {
produto.setId(Integer.parseInt(idStr));
}
produto.setNome(nome);
produto.setPreco(preco);
produto.setCategoria(categoria);
// Salva
if (produto.getId() == 0) {
produtoDAO.inserir(produto);
request.setAttribute("mensagem", "Produto inserido com sucesso!");
} else {
produtoDAO.atualizar(produto);
request.setAttribute("mensagem", "Produto atualizado com sucesso!");
}
// Prepara para próxima exibição
request.setAttribute("categorias", categoriaDAO.listarTodos());
request.setAttribute("produtos", produtoDAO.listarTodos());
} catch (Exception e) {
request.setAttribute("erro", "Erro: " + e.getMessage());
}
request.getRequestDispatcher("/produtos.jsp").forward(request, response);
}
}
CREATE TABLE categorias (
id INT AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(100) NOT NULL
);
CREATE TABLE produtos (
id INT AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(100) NOT NULL,
preco DECIMAL(10,2) NOT NULL,
categoria_id INT,
FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);
INSERT INTO categorias (nome) VALUES
('Eletrônicos'), ('Informática'), ('Celulares');
// Exemplo de transação completa em JDBC
Connection conn = null;
try {
conn = ConnectionFactory.getConnection();
// Desabilita o autocommit para iniciar transação
conn.setAutoCommit(false);
// Operação 1: Atualizar saldo da conta origem
PreparedStatement stmt1 = conn.prepareStatement(
"UPDATE contas SET saldo = saldo - ? WHERE id = ?");
stmt1.setDouble(1, valor);
stmt1.setInt(2, contaOrigem);
int rows1 = stmt1.executeUpdate();
// Operação 2: Atualizar saldo da conta destino
PreparedStatement stmt2 = conn.prepareStatement(
"UPDATE contas SET saldo = saldo + ? WHERE id = ?");
stmt2.setDouble(1, valor);
stmt2.setInt(2, contaDestino);
int rows2 = stmt2.executeUpdate();
// Verifica se ambas as operações afetaram linhas
if (rows1 > 0 && rows2 > 0) {
// Confirma a transação
conn.commit();
} else {
// Desfaz a transação
conn.rollback();
throw new SQLException("Falha na transferência.");
}
} catch (Exception e) {
// Em caso de erro, desfaz a transação
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
throw e;
} finally {
// Restaura o autocommit
if (conn != null) {
try {
conn.setAutoCommit(true);
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class PessoaDAOTest {
private PessoaDAO dao;
private Pessoa pessoa;
@Before
public void setUp() {
dao = new PessoaDAOImpl();
pessoa = new Pessoa();
pessoa.setNome("Teste");
pessoa.setEmail("teste@example.com");
}
@Test
public void testInserir() throws SQLException {
dao.inserir(pessoa);
assertTrue(pessoa.getId() > 0);
Pessoa recuperada = dao.buscarPorId(pessoa.getId());
assertEquals(pessoa.getNome(), recuperada.getNome());
assertEquals(pessoa.getEmail(), recuperada.getEmail());
}
@Test
public void testAtualizar() throws SQLException {
dao.inserir(pessoa);
pessoa.setNome("Teste Atualizado");
dao.atualizar(pessoa);
Pessoa recuperada = dao.buscarPorId(pessoa.getId());
assertEquals("Teste Atualizado", recuperada.getNome());
}
@Test
public void testExcluir() throws SQLException {
dao.inserir(pessoa);
dao.excluir(pessoa.getId());
Pessoa recuperada = dao.buscarPorId(pessoa.getId());
assertNull(recuperada);
}
@Test(expected = SQLException.class)
public void testInserirEmailDuplicado() throws SQLException {
dao.inserir(pessoa);
Pessoa outraPessoa = new Pessoa();
outraPessoa.setNome("Outro");
outraPessoa.setEmail("teste@example.com"); // Mesmo email
dao.inserir(outraPessoa); // Deve lançar SQLException
}
}
// NUNCA FAÇA ISSO:
String sql = "SELECT * FROM usuarios WHERE email = '" + email + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
// FAÇA ISSO:
String sql = "SELECT * FROM usuarios WHERE email = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, email);
ResultSet rs = stmt.executeQuery();
try {
// Lógica de negócio
dao.inserir(objeto);
// Mensagem de sucesso
request.setAttribute("mensagem",
"Operação realizada com sucesso!");
} catch (SQLException e) {
// Log detalhado para depuração
logger.error("Erro ao inserir: " + e.getMessage(), e);
// Mensagem amigável para o usuário
String msgUsuario = "Não foi possível realizar a operação.";
if (e.getErrorCode() == 1062) { // MySQL duplicate key
msgUsuario = "Este registro já existe no sistema.";
} else if (e.getErrorCode() == 1451) { // MySQL foreign key
msgUsuario = "Este registro não pode ser excluído pois está sendo usado em outro cadastro.";
}
request.setAttribute("erro", msgUsuario);
} finally {
// Redirecionamento consistente
request.getRequestDispatcher("/pagina.jsp")
.forward(request, response);
}
CREATE TABLE categorias (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(50) NOT NULL
);
CREATE TABLE produtos (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(100) NOT NULL,
descricao TEXT,
preco DECIMAL(10,2) NOT NULL,
estoque INT NOT NULL DEFAULT 0,
categoria_id INT,
data_cadastro TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);