BAB 16 – Membangun REST API Sederhana dengan MySQL (mysql2) dan Express.js

BAB 16 – Membangun REST API Sederhana dengan MySQL (mysql2) dan Express.js

Di bab ini kita benar-benar membuat REST API yang dipakai di dunia nyata, bukan simulasi array.
Namun tetap simple dan masuk akal untuk blog, tanpa ORM, tanpa struktur berlebihan.

Target API:

  • CRUD data dari MySQL
  • koneksi database pakai mysql2
  • query SQL langsung (mudah dipahami)
  • struktur backend rapi tapi tidak ribet

Studi kasus: Data Produk


Struktur Folder Backend yang Digunakan

Struktur ini cukup profesional tapi tetap sederhana:

backend/
├── src/
│   ├── routes/
│   │   └── product.routes.js
│   ├── controllers/
│   │   └── product.controller.js
│   ├── db/
│   │   └── mysql.js
│   └── app.js
├── index.js
├── package.json

Tidak ada service layer dulu → biar fokus MySQL + REST API.


Membuat Database dan Tabel MySQL

Buat database dan tabel sederhana:

CREATE DATABASE node_api;

USE node_api;

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100),
  price INT
);

Struktur ini cukup untuk latihan REST API.


Install mysql2

npm install express mysql2

mysql2 dipilih karena:

  • cepat
  • stabil
  • paling umum dipakai di Node.js

Koneksi MySQL Menggunakan mysql2

// src/db/mysql.js
import mysql from "mysql2/promise";

const db = mysql.createPool({
  host: "localhost",
  user: "root",
  password: "",
  database: "node_api"
});

export default db;

Kenapa createPool?

  • koneksi lebih stabil
  • cocok untuk API

Setup Aplikasi Express

// src/app.js
import express from "express";
import productRoutes from "./routes/product.routes.js";

const app = express();

app.use(express.json());
app.use("/api/products", productRoutes);

export default app;

Entry Point Server

// index.js
import app from "./src/app.js";

app.listen(3000, () => {
  console.log("Server berjalan di http://localhost:3000");
});

Controller: Ambil Semua Produk (GET)

// src/controllers/product.controller.js
import db from "../db/mysql.js";

export async function getProducts(req, res) {
  const [rows] = await db.query("SELECT * FROM products");

  res.json({
    success: true,
    data: rows
  });
}

Ini REST API nyata, langsung query ke MySQL.


Controller: Ambil Produk by ID

export async function getProductById(req, res) {
  const id = req.params.id;

  const [rows] = await db.query(
    "SELECT * FROM products WHERE id = ?",

); if (rows.length === 0) { return res.status(404).json({ message: "Produk tidak ditemukan" }); } res.json({ success: true, data: rows[0] }); }

? mencegah SQL Injection → WAJIB.


Controller: Tambah Produk (POST)

export async function createProduct(req, res) {
  const { name, price } = req.body;

  if (!name || !price) {
    return res.status(400).json({
      message: "Name dan price wajib diisi"
    });
  }

  const [result] = await db.query(
    "INSERT INTO products (name, price) VALUES (?, ?)",

); res.status(201).json({ success: true, data: { id: result.insertId, name, price } }); }

Controller: Update Produk (PUT)

export async function updateProduct(req, res) {
  const id = req.params.id;
  const { name, price } = req.body;

  const [result] = await db.query(
    "UPDATE products SET name = ?, price = ? WHERE id = ?",

); if (result.affectedRows === 0) { return res.status(404).json({ message: "Produk tidak ditemukan" }); } res.json({ success: true, message: "Produk berhasil diupdate" }); }

Controller: Hapus Produk (DELETE)

export async function deleteProduct(req, res) {
  const id = req.params.id;

  const [result] = await db.query(
    "DELETE FROM products WHERE id = ?",

); if (result.affectedRows === 0) { return res.status(404).json({ message: "Produk tidak ditemukan" }); } res.json({ success: true, message: "Produk berhasil dihapus" }); }

Routing REST API Produk

// src/routes/product.routes.js
import express from "express";
import {
  getProducts,
  getProductById,
  createProduct,
  updateProduct,
  deleteProduct
} from "../controllers/product.controller.js";

const router = express.Router();

router.get("/", getProducts);
router.get("/:id", getProductById);
router.post("/", createProduct);
router.put("/:id", updateProduct);
router.delete("/:id", deleteProduct);

export default router;

Daftar Endpoint REST API

MethodEndpointFungsi
GET/api/productsAmbil semua produk
GET/api/products/:idDetail produk
POST/api/productsTambah produk
PUT/api/products/:idUpdate produk
DELETE/api/products/:idHapus produk

Ini REST API MySQL yang benar dan minimal.


Contoh Testing (POST)

Body JSON:

{
  "name": "Keyboard",
  "price": 300000
}

Response:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Keyboard",
    "price": 300000
  }
}

Kenapa Pendekatan Ini Ideal untuk Blog

✔ pakai database sungguhan
✔ kode singkat dan jelas
✔ tidak terlalu abstrak
✔ mudah dikembangkan ke JWT & auth
✔ cocok untuk pembaca pemula–menengah

Ini bukan contoh murahan, tapi fondasi backend nyata.


Kesimpulan

Dengan mysql2 dan Express:

  • REST API bisa dibuat ringkas dan profesional
  • tidak perlu ORM untuk belajar konsep backend
  • alur data jadi jelas dan logis

Bab ini adalah jembatan ke backend serius.