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 ProdutoDTOProduto com população da lista de categorias;
  • Uso de @Transactional, @CreationTimestamp, @UpdateTimestamp, Set<Categoria>;
  • Boas práticas com método copyDtoToProduto(...) no Service.

🔹 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! 🚀

Categorized in:

Backend, Spring Boot,