🚀 5.4 CRUD de Elite: Implementação Ponta a Ponta
As rotinas de CRUD (Create, Retrieve, Update, Delete) são o alicerce de qualquer sistema de gestão. Na Engenharia Premium, implementamos essas rotinas focando em Consistência, Validação e UX Fluida.
A Arquitetura do CRUD
O ciclo de vida de uma entidade no Green Dog (exemplo: Cliente) é orquestrado por três pilares:
- Controller: O cérebro que decide o fluxo.
- Repository: A ponte segura com o banco de dados.
- Templates: A interface de alta fidelidade para o usuário.
🎮 O Controller de Elite
Utilizamos Injeção de Dependência via Construtor e anotações semânticas modernas no ClienteController.
@Controller
@RequestMapping("/clientes")
@RequiredArgsConstructor
public class ClienteController {
private final ClienteRepository clienteRepository;
@GetMapping
public ModelAndView list() {
return new ModelAndView("clientes/list", "clientes", clienteRepository.findAll());
}
@GetMapping("/{id}")
public ModelAndView view(@PathVariable("id") Cliente cliente) {
return new ModelAndView("clientes/view", "cliente", cliente);
}
@GetMapping("/novo")
public String createForm(@ModelAttribute Cliente cliente) {
return "clientes/form";
}
@PostMapping
public String save(@Valid Cliente cliente, BindingResult result, RedirectAttributes redirect) {
if (result.hasErrors()) return "clientes/form";
clienteRepository.save(cliente);
redirect.addFlashAttribute("globalMessage", "Cliente processado com sucesso!");
return "redirect:/clientes/" + cliente.getId();
}
@GetMapping("/remover/{id}")
public String delete(@PathVariable Long id, RedirectAttributes redirect) {
clienteRepository.deleteById(id);
redirect.addFlashAttribute("globalMessage", "Cliente removido!");
return "redirect:/clientes";
}
}🎨 Interfaces de Alta Fidelidade (Thymeleaf + Bootstrap 5)
1. Lista de Clientes (list.html)
Focada em legibilidade e ação rápida.
<section layout:fragment="content" class="container mt-4">
<div class="d-flex justify-content-between mb-3">
<h1>Lista de Clientes</h1>
<a th:href="@{/clientes/novo}" class="btn btn-primary">Novo Cliente</a>
</div>
<table class="table table-hover shadow-sm">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
<tr th:each="c : ${clientes}">
<td th:text="${c.id}">01</td>
<td>
<a th:href="@{/clientes/{id}(id=${c.id})}" th:text="${c.nome}">Nome</a>
</td>
<td>
<a th:href="@{/clientes/alterar/{id}(id=${c.id})}" class="btn btn-sm btn-outline-secondary">Editar</a>
</td>
</tr>
</tbody>
</table>
</section>2. Formulário de Cadastro (form.html)
Implementa validações visuais em tempo real.
<section layout:fragment="content" class="container mt-4">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h2 class="h5 mb-0">Cadastro de Cliente</h2>
</div>
<div class="card-body">
<form th:action="@{/clientes}" th:object="${cliente}" method="post">
<input type="hidden" th:field="*{id}">
<div class="mb-3">
<label class="form-label">Nome Completo</label>
<input type="text" th:field="*{nome}" class="form-control"
th:classappend="${#fields.hasErrors('nome')} ? 'is-invalid'">
<div class="invalid-feedback" th:errors="*{nome}">Erro</div>
</div>
<div class="mb-3">
<label class="form-label">Endereço de Entrega</label>
<textarea th:field="*{endereco}" class="form-control" rows="3"></textarea>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a th:href="@{/clientes}" class="btn btn-light me-md-2">Cancelar</a>
<button type="submit" class="btn btn-success px-5">Gravar</button>
</div>
</form>
</div>
</div>
</section>🛠️ Padrões de Elite Aplicados
- POST-Redirect-GET (PRG): Após salvar, redirecionamos o usuário. Isso evita o reenvio acidental de dados ao atualizar a página (F5).
- Flash Attributes: Mensagens de sucesso que “sobrevivem” ao redirecionamento, desaparecendo após serem exibidas uma única vez.
- Binding Automático: O Spring Boot converte os campos do HTML diretamente para os atributos da nossa entidade
Cliente.
TIP
No Spring Boot 3.5, o suporte a Bean Validation está mais robusto do que nunca. Sinta-se livre para adicionar anotações complexas em suas entidades; o Controller as processará automaticamente via
@Valid.
Agora que dominamos o CRUD básico, como lidaremos com milhares de registros? Veremos isso no capítulo de Paginação.