Neste artigo vamos complementar a aula do YouTube onde implementamos o cadastro de produtos com múltiplas categorias utilizando Spring Boot, JPA e DTOs. A proposta foi trabalhar um CRUD completo com relacionamento do tipo muitos-para-muitos (N:N) entre Produto
e Categoria
.
📺 Assista ao vídeo completo no YouTube: https://youtu.be/8PXIQ6L_WWM
Essa estrutura é muito comum em sistemas de e-commerce, catálogos ou marketplaces, onde um produto pode pertencer a várias categorias e vice-versa.
✨ O que foi implementado
- Entidade
Produto
com anotações@ManyToMany
e campos de auditoria (createdAt
,updatedAt
); - CRUD completo para
Produto
(listar, buscar por id, salvar, atualizar, deletar); - Conversão de
ProdutoDTO
→Produto
com população da lista de categorias; - Uso de
@Transactional
,@CreationTimestamp
,@UpdateTimestamp
,Set<Categoria>
; - Boas práticas com método
copyDtoToProduto(...)
noService
.
🔹 Relacionamento Produto x Categoria
Na entidade Produto
, o relacionamento foi definido assim:
@ManyToMany
@JoinTable(name = "produto_categoria",
joinColumns = @JoinColumn(name = "produto_id"),
inverseJoinColumns = @JoinColumn(name = "categoria_id")
)
private Set<Categoria> categorias = new HashSet<>();
Esse mapeamento cria uma tabela associativa chamada produto_categoria
, com as chaves estrangeiras produto_id
e categoria_id
.
🔄 Conversão DTO → Entidade
Criamos o método abaixo para copiar os dados do DTO para a entidade Produto
:
private void copyDtoToProduto(ProdutoDTO dto, Produto produto) {
produto.setNome(dto.getNome());
produto.setDescricao(dto.getDescricao());
produto.setPreco(dto.getPreco());
produto.setImgUrl(dto.getImgUrl());
produto.getCategorias().clear();
for (CategoriaDTO categoriaDTO : dto.getCategorias()) {
Categoria categoria = categoriaRepository.getReferenceById(categoriaDTO.getId());
produto.getCategorias().add(categoria);
}
}
Esse método é usado tanto em salvarProduto
quanto em atualizarProduto
, garantindo consistência na manipulação dos dados.
🚀 Testando a API com Postman
POST – Cadastrando Produto com Categorias
Endpoint: POST http://localhost:8080/produto
{
"nome": "Casa de Alqueria D.O. Valle Central Carménère 2024",
"preco": 42.50,
"descricao": "Casa de Alqueria é uma linha de vinhos jovens, amigáveis e descomplicados elaborada pela Cremaschi Barriga...",
"imgUrl": "",
"categorias": [
{ "id": 1 },
{ "id": 5 }
]
}
Esse comando cria um produto e associa às categorias com id = 1
e id = 5
.
PUT – Atualizando Produto com Categorias
Endpoint: PUT http://localhost:8080/produto/13
{
"nome": "Casa de Alqueria D.O. Valle Central Carménère 2024",
"preco": 18.99,
"descricao": "Casa de Alqueria é uma linha de vinhos jovens, amigáveis e descomplicados elaborada pela Cremaschi Barriga...",
"imgUrl": "",
"categorias": [
{ "id": 1 },
{ "id": 5 }
]
}
Esse comando atualiza completamente o produto com ID 13 e substitui as categorias.
⚠️ O método
PUT
é destrutivo: ele limpa todas as categorias anteriores e substitui pelas informadas.
📊 Conclusão
Esse foi mais um passo importante na evolução do nosso backend com Spring Boot, mostrando como lidar com relacionamentos N:N de forma segura, controlada e performável.
Na próxima aula, podemos evoluir para:
- Listagem com filtro por categoria
- Busca por nome com
LIKE
- Validação com
@Valid
- E claro, testes automatizados!
Continue acompanhando nossa trilha e bons códigos! 🚀