Desenvolvimento Web

Como criar um CRUD com Node.js e MySQL do zero ao deploy

Como criar um CRUD com Node.js e MySQL do zero ao deploy

CRUD (Create, Read, Update, Delete) é a base de quase toda aplicação que armazena dados. Saber construir um CRUD completo com Node.js e MySQL é um milestone importante para qualquer desenvolvedor backend — com isso você consegue criar a estrutura de qualquer sistema de cadastro, gerenciamento ou API. Este tutorial cria uma API REST de cadastro de produtos do zero, com banco de dados MySQL, rodando localmente e pronto para deploy.

Setup: Node.js + MySQL

Você precisa do Node.js instalado (nodejs.org) e de um MySQL rodando localmente. A forma mais simples de ter MySQL sem instalar diretamente: Docker. Com Docker instalado, um único comando sobe o MySQL:

docker run -d 
  --name mysql-crud 
  -e MYSQL_ROOT_PASSWORD=senha123 
  -e MYSQL_DATABASE=crud_db 
  -p 3306:3306 
  mysql:8

Crie a pasta do projeto e inicialize:

mkdir node-crud && cd node-crud
npm init -y
npm install express mysql2 dotenv
npm install -D nodemon

Criando a tabela no MySQL

CREATE TABLE produtos (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nome VARCHAR(100) NOT NULL,
  preco DECIMAL(10, 2) NOT NULL,
  estoque INT DEFAULT 0,
  criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Estrutura do projeto

node-crud/
├── .env
├── index.js
├── db.js
└── routes/
    └── produtos.js

Arquivo .env:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=senha123
DB_NAME=crud_db
PORT=3000

Arquivo db.js — conexão com o banco:

const mysql = require('mysql2/promise');
require('dotenv').config();

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
});

module.exports = pool;

As rotas CRUD

Arquivo routes/produtos.js:

const express = require('express');
const router = express.Router();
const db = require('../db');

// READ ALL — GET /produtos
router.get('/', async (req, res) => {
  const [rows] = await db.query('SELECT * FROM produtos ORDER BY id DESC');
  res.json(rows);
});

// READ ONE — GET /produtos/:id
router.get('/:id', async (req, res) => {
  const [rows] = await db.query('SELECT * FROM produtos WHERE id = ?', [req.params.id]);
  if (rows.length === 0) return res.status(404).json({ erro: 'Produto não encontrado' });
  res.json(rows[0]);
});

// CREATE — POST /produtos
router.post('/', async (req, res) => {
  const { nome, preco, estoque } = req.body;
  if (!nome || !preco) return res.status(400).json({ erro: 'Nome e preço são obrigatórios' });
  const [result] = await db.query(
    'INSERT INTO produtos (nome, preco, estoque) VALUES (?, ?, ?)',
    [nome, preco, estoque || 0]
  );
  res.status(201).json({ id: result.insertId, nome, preco, estoque: estoque || 0 });
});

// UPDATE — PUT /produtos/:id
router.put('/:id', async (req, res) => {
  const { nome, preco, estoque } = req.body;
  const [result] = await db.query(
    'UPDATE produtos SET nome = ?, preco = ?, estoque = ? WHERE id = ?',
    [nome, preco, estoque, req.params.id]
  );
  if (result.affectedRows === 0) return res.status(404).json({ erro: 'Produto não encontrado' });
  res.json({ mensagem: 'Produto atualizado com sucesso' });
});

// DELETE — DELETE /produtos/:id
router.delete('/:id', async (req, res) => {
  const [result] = await db.query('DELETE FROM produtos WHERE id = ?', [req.params.id]);
  if (result.affectedRows === 0) return res.status(404).json({ erro: 'Produto não encontrado' });
  res.json({ mensagem: 'Produto removido com sucesso' });
});

module.exports = router;

Arquivo index.js:

const express = require('express');
require('dotenv').config();
const app = express();

app.use(express.json());
app.use('/produtos', require('./routes/produtos'));

app.listen(process.env.PORT, () => {
  console.log(`Servidor rodando na porta ${process.env.PORT}`);
});

Testando e fazendo deploy

Rode com npx nodemon index.js e teste com Thunder Client no VS Code ou cURL: curl http://localhost:3000/produtos. Para deploy gratuito: Railway.app suporta Node.js + MySQL com plano free generoso — você conecta o repositório GitHub e o deploy acontece automaticamente a cada push. Render.com e Fly.io são alternativas igualmente sólidas para projetos iniciais. Com esse projeto no GitHub e um deploy funcionando, você tem um portfólio concreto de backend que cobre as operações fundamentais de qualquer sistema.

Tem um projeto em mente?

Somos especialistas em transformar ideias em produtos digitais. Apps, sites, automações e IA — vamos construir juntos.

Resposta rápida Orçamento sem compromisso +100 projetos entregues
Compartilhar: