Produto com Categoria.java -version).~/apache-tomcat-10).loja CREATE DATABASE loja DEFAULT CHARACTER SET utf8mb4;
USE loja;
mvn archetype:generate -DgroupId=br.com.mantovanitech -DartifactId=crud-produtos \
-DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
cd crud-produtos
pom.xml para usar Java 17, Servlet 6, JSTL e driver JDBC:<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Servlet API (Tomcat 10 usa jakarta.servlet 6) -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
<!-- Driver JDBC (escolha um) -->
<!-- MySQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
<!-- OU H2 (comentando o de cima) -->
<!--
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
<scope>runtime</scope>
</dependency>
-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
br.com.mantovanitech
├─ model (JavaBeans)
├─ dao (interfaces e impls)
├─ util (ConnectionFactory)
└─ controller (Servlets)
src/main/webapp/.USE loja;
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,
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)
);
INSERT INTO categorias (nome) VALUES ('Eletrônicos'), ('Informática'), ('Celulares');
update/delete quando necessário).durante essa hora, já deixe prontos os esqueletos de classe (abaixo) para acelerar a prática.
// model/Categoria.java
package br.com.mantovanitech.model;
import java.io.Serializable;
public class Categoria implements Serializable {
private int id;
private String nome;
public Categoria() {}
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; }
}
// model/Produto.java
package br.com.mantovanitech.model;
import java.io.Serializable;
import java.math.BigDecimal;
public class Produto implements Serializable {
private int id;
private String nome;
private String descricao;
private BigDecimal preco;
private int estoque;
private Categoria categoria;
public Produto() {}
// getters/setters …
}
// util/ConnectionFactory.java
package br.com.mantovanitech.util;
import java.sql.*;
public class ConnectionFactory {
private static final String URL = "jdbc:mysql://localhost:3306/loja?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASS = "sua_senha";
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASS);
}
}
usando H2? troque a URL porjdbc:h2:~/loja;MODE=MySQL;AUTO_SERVER=TRUEe remova o driver MySQL dopom.
// dao/ProdutoDAO.java
package br.com.mantovanitech.dao;
import br.com.mantovanitech.model.*;
import java.sql.SQLException;
import java.util.List;
public interface ProdutoDAO {
void inserir(Produto p) throws SQLException;
Produto buscarPorId(int id) throws SQLException;
List<Produto> listarTodos() throws SQLException;
void atualizar(Produto p) throws SQLException;
void excluir(int id) throws SQLException;
}
// dao/impl/ProdutoDAOImpl.java
package br.com.mantovanitech.dao.impl;
import br.com.mantovanitech.dao.ProdutoDAO;
import br.com.mantovanitech.model.*;
import br.com.mantovanitech.util.ConnectionFactory;
import java.sql.*;
import java.math.BigDecimal;
import java.util.*;
public class ProdutoDAOImpl implements ProdutoDAO {
@Override
public void inserir(Produto p) throws SQLException {
String sql = "INSERT INTO produtos (nome, descricao, preco, estoque, categoria_id) VALUES (?,?,?,?,?)";
try (Connection c = ConnectionFactory.getConnection();
PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.setString(1, p.getNome());
ps.setString(2, p.getDescricao());
ps.setBigDecimal(3, p.getPreco());
ps.setInt(4, p.getEstoque());
ps.setInt(5, p.getCategoria().getId());
int rows = ps.executeUpdate();
if (rows == 0) throw new SQLException("Nenhuma linha inserida.");
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) p.setId(rs.getInt(1));
}
}
}
@Override
public Produto buscarPorId(int id) throws SQLException {
String sql = """
SELECT p.id,p.nome,p.descricao,p.preco,p.estoque,
c.id AS cat_id, c.nome AS cat_nome
FROM produtos p LEFT JOIN categorias c ON c.id = p.categoria_id
WHERE p.id = ?
""";
try (Connection c = ConnectionFactory.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, id);
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) return null;
return map(rs);
}
}
}
@Override
public List<Produto> listarTodos() throws SQLException {
String sql = """
SELECT p.id,p.nome,p.descricao,p.preco,p.estoque,
c.id AS cat_id, c.nome AS cat_nome
FROM produtos p LEFT JOIN categorias c ON c.id = p.categoria_id
ORDER BY p.id DESC
""";
List<Produto> out = new ArrayList<>();
try (Connection c = ConnectionFactory.getConnection();
PreparedStatement ps = c.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) out.add(map(rs));
}
return out;
}
@Override
public void atualizar(Produto p) throws SQLException {
String sql = "UPDATE produtos SET nome=?, descricao=?, preco=?, estoque=?, categoria_id=? WHERE id=?";
try (Connection c = ConnectionFactory.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
c.setAutoCommit(false);
try {
ps.setString(1, p.getNome());
ps.setString(2, p.getDescricao());
ps.setBigDecimal(3, p.getPreco());
ps.setInt(4, p.getEstoque());
ps.setInt(5, p.getCategoria().getId());
ps.setInt(6, p.getId());
int rows = ps.executeUpdate();
if (rows == 0) throw new SQLException("Nada atualizado.");
c.commit();
} catch (Exception e) { c.rollback(); throw e; }
finally { c.setAutoCommit(true); }
}
}
@Override
public void excluir(int id) throws SQLException {
String sql = "DELETE FROM produtos WHERE id=?";
try (Connection c = ConnectionFactory.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, id);
int rows = ps.executeUpdate();
if (rows == 0) throw new SQLException("Registro não encontrado.");
}
}
private Produto map(ResultSet rs) throws SQLException {
Produto p = new Produto();
p.setId(rs.getInt("id"));
p.setNome(rs.getString("nome"));
p.setDescricao(rs.getString("descricao"));
p.setPreco(rs.getBigDecimal("preco"));
p.setEstoque(rs.getInt("estoque"));
Categoria c = new Categoria();
c.setId(rs.getInt("cat_id"));
c.setNome(rs.getString("cat_nome"));
p.setCategoria(c);
return p;
}
}
crie também umCategoriaDAOsimples comlistarTodos()ebuscarPorId()(estruturalmente idêntico).
// controller/ProdutoServlet.java
package br.com.mantovanitech.controller;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import jakarta.servlet.ServletException;
import java.io.IOException;
import br.com.mantovanitech.dao.impl.ProdutoDAOImpl;
import br.com.mantovanitech.dao.impl.CategoriaDAOImpl; // crie este
import br.com.mantovanitech.model.*;
import java.math.BigDecimal;
@WebServlet("/produtos")
public class ProdutoServlet extends HttpServlet {
private final ProdutoDAOImpl produtoDAO = new ProdutoDAOImpl();
private final CategoriaDAOImpl categoriaDAO = new CategoriaDAOImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String acao = req.getParameter("acao");
try {
if ("editar".equals(acao)) {
int id = Integer.parseInt(req.getParameter("id"));
req.setAttribute("produto", produtoDAO.buscarPorId(id));
} else if ("excluir".equals(acao)) {
int id = Integer.parseInt(req.getParameter("id"));
produtoDAO.excluir(id);
req.setAttribute("mensagem", "Excluído com sucesso!");
}
req.setAttribute("categorias", categoriaDAO.listarTodos());
req.setAttribute("produtos", produtoDAO.listarTodos());
} catch (Exception e) {
req.setAttribute("erro", e.getMessage());
}
req.getRequestDispatcher("/WEB-INF/views/produtos.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String id = req.getParameter("id");
String nome = req.getParameter("nome");
String descricao = req.getParameter("descricao");
String preco = req.getParameter("preco");
String estoque = req.getParameter("estoque");
String categoriaId = req.getParameter("categoriaId");
try {
// validação mínima
if (nome == null || nome.isBlank()) throw new IllegalArgumentException("Nome é obrigatório.");
Produto p = new Produto();
if (id != null && !id.isBlank()) p.setId(Integer.parseInt(id));
p.setNome(nome);
p.setDescricao(descricao);
p.setPreco(new BigDecimal(preco));
p.setEstoque(Integer.parseInt(estoque));
Categoria c = categoriaDAO.buscarPorId(Integer.parseInt(categoriaId));
p.setCategoria(c);
if (p.getId() == 0) {
produtoDAO.inserir(p);
req.setAttribute("mensagem", "Inserido com sucesso!");
} else {
produtoDAO.atualizar(p);
req.setAttribute("mensagem", "Atualizado com sucesso!");
}
req.setAttribute("categorias", categoriaDAO.listarTodos());
req.setAttribute("produtos", produtoDAO.listarTodos());
} catch (Exception e) {
req.setAttribute("erro", "Falha: " + e.getMessage());
}
req.getRequestDispatcher("/WEB-INF/views/produtos.jsp").forward(req, resp);
}
}
src/main/webapp/WEB-INF/views/produtos.jsp:<%@ page 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>Produtos</title></head>
<body>
<h1>Cadastro de Produto</h1>
<c:if test="${not empty mensagem}">
<div style="color:green">${mensagem}</div>
</c:if>
<c:if test="${not empty erro}">
<div style="color:red">${erro}</div>
</c:if>
<form action="${pageContext.request.contextPath}/produtos" method="post">
<input type="hidden" name="id" value="${produto.id}"/>
<div>Nome: <input name="nome" value="${produto.nome}" required></div>
<div>Descrição: <input name="descricao" value="${produto.descricao}"></div>
<div>Preço: <input type="number" step="0.01" name="preco" value="${produto.preco}" required></div>
<div>Estoque: <input type="number" name="estoque" value="${produto.estoque}" required></div>
<div>Categoria:
<select name="categoriaId" required>
<option value="">Selecione…</option>
<c:forEach items="${categorias}" var="cat">
<option value="${cat.id}" <c:if test="${produto.categoria != null && produto.categoria.id == cat.id}">selected</c:if>>
${cat.nome}
</option>
</c:forEach>
</select>
</div>
<button type="submit">Salvar</button>
</form>
<h2>Produtos</h2>
<table border="1" cellpadding="6">
<tr><th>ID</th><th>Nome</th><th>Preço</th><th>Estoque</th><th>Categoria</th><th>Ações</th></tr>
<c:forEach items="${produtos}" var="p">
<tr>
<td>${p.id}</td>
<td>${p.nome}</td>
<td>R$ ${p.preco}</td>
<td>${p.estoque}</td>
<td>${p.categoria.nome}</td>
<td>
<a href="${pageContext.request.contextPath}/produtos?acao=editar&id=${p.id}">Editar</a>
<a href="${pageContext.request.contextPath}/produtos?acao=excluir&id=${p.id}" onclick="return confirm('Confirma exclusão?')">Excluir</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
src/main/webapp/WEB-INF/web.xml (opcional) apenas se quiser bem definido o welcome:<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" version="6.0">
<display-name>CRUD Produtos</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
src/main/webapp/index.jsp para redirecionar:<% response.sendRedirect(request.getContextPath() + "/produtos"); %>
mvn clean package
target/crud-produtos.war. deploy no Tomcat:.war para tomcat/webapps/ ou use a extensão Tomcat for Java no VS Code.http://localhost:8080/crud-produtos/Servlet (mínimo implementado).${erro} / ${mensagem}).SELECT ... LIMIT ?, ?.mvn clean package).try-with-resources, sem SQL concatenado./db/schema.sql + /db/seed.sql)./docs/.



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)
);