PostgreSQL telah terhubung, dan kabar baiknya adalah keterampilan itu tidak berpindah jauh. MySQL — beserta turunannya MariaDB — adalah database client-server yang sama populernya, dipakai dari aplikasi web kecil hingga layanan berskala besar. Driver andalannya di ekosistem Node.js adalah package mysql2, dan meskipun tugasnya sama dengan pg, gaya API-nya memilih keputusan desain yang berbeda di beberapa titik penting. Chapter ini menyambungkan Node.js ke MySQL, lalu memetakan perbedaan-perbedaan tersebut agar kita luwes berpindah antar driver.

Menginstal Driver mysql2 #

Driver mysql2 dikembangkan di repositori node-mysql2 dan dipasang seperti biasa:

bash
npm install mysql2

API Promise dan Bentuk Hasilnya #

Paket mysql2 menawarkan dua pintu: mysql2 berbasis callback, dan mysql2/promise berbasis Promise. Kita langsung memakai yang kedua — cukup ganti jalur impor. Sebuah koneksi tunggal dibuat lewat createConnection, dan berbeda dari pg, function ini sekaligus melakukan penyambungan sehingga tidak ada panggilan connect() terpisah:

js Koneksi tunggal dengan mysql2/promise
import mysql from 'mysql2/promise';

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

const [rows] = await conn.execute(
  'SELECT id, judul FROM tugas WHERE selesai = ?',
  [false]
);

console.log(rows);

await conn.end();

Dua perbedaan mencolok langsung terlihat. Pertama, hasil execute() berbentuk array dua elemen [rows, fields] — baris data di elemen pertama, metadata kolom di elemen kedua — sehingga kita mendestruksinya dengan const [rows]. Kedua, placeholder MySQL memakai tanda tanya posisional ?, bukan penomoran $1 ala PostgreSQL. Parameter tetap dikirim terpisah dari teks SQL, sehingga keamanannya setara.

Peta Perbedaan pg dan mysql2 #

Aspekpgmysql2
Placeholder$1, $2, …?
Bentuk hasil queryObject { rows, rowCount, ... }Array [rows, fields]
Membuka koneksinew Client() lalu await client.connect()await mysql.createConnection(...) sekaligus
Menutup koneksiawait client.end()await conn.end()
Konfigurasi targetConnection string satu URLObject host, user, password, database
PoolClass Poolmysql.createPool(...)

Table di atas adalah contekan yang layak ditempel di meja. Pola besar keduanya identik — sambungkan, kirim query berparameter, olas hasilnya, tutup — yang berubah hanya ejaan detailnya. Konfigurasi mysql2 memang lebih bertabur property karena MySQL tidak memiliki satu format connection string yang sestandar postgresql:// di kalangan tool-nya.

Kredensial dengan Berkas .env #

Sama seperti pada Chapter sebelumnya, kredensial database tidak ditulis di kode sumber. Berkas .env menampung konfigurasi koneksi dalam bentuk variabel lingkungan, lalu dimuat dengan flag --env-file:

text Isi berkas .env
DB_HOST=localhost
DB_PORT=3306
DB_USER=pengguna
DB_PASSWORD=YOUR_DATABASE_PASSWORD
DB_NAME=tugasdb
bash
node --env-file=.env aplikasi.mjs

Berkas Contoh Lengkap #

Berkas berikut memakai pool — dibuat dengan mysql.createPool dan opsi connectionLimit — untuk membuat tabel, menyisipkan satu baris, lalu membacanya:

js
// contoh-mysql.mjs — butuh server MySQL berjalan (tidak diuji di Course ini).
// Persiapan:
//   1. npm install mysql2
//   2. Buat berkas .env (lihat Chapter) lalu jalankan:
//      node --env-file=.env contoh-mysql.mjs
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT ?? 3306),
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  connectionLimit: 10,
});

async function main() {
  await pool.query(`
    CREATE TABLE IF NOT EXISTS tugas (
      id INT AUTO_INCREMENT PRIMARY KEY,
      judul VARCHAR(255) NOT NULL,
      selesai BOOLEAN NOT NULL DEFAULT FALSE
    )
  `);

  // API promise mengembalikan array [rows, fields].
  const [hasil] = await pool.execute(
    'INSERT INTO tugas (judul, selesai) VALUES (?, ?)',
    ['Belajar MySQL', false]
  );
  console.log('Tugas baru, id:', hasil.insertId);

  const [rows] = await pool.execute('SELECT * FROM tugas ORDER BY id');
  console.log('Daftar tugas:', rows);

  await pool.end();
}

main().catch((error) => {
  console.error('Koneksi atau query gagal:', error.message);
  process.exit(1);
});

Beberapa detail MySQL yang baru di sini perlu dijelaskan. Tipe INT AUTO_INCREMENT PRIMARY KEY adalah padanan SERIAL di PostgreSQL: server menomori baris baru secara otomatis. Setelah INSERT, id yang diberikan server tersedia di hasil.insertId — padanan lastInsertRowid pada node:sqlite dan RETURNING pada pg. Kolom teks memakai VARCHAR(255) dengan batas panjang eksplisit, dan nilai boolean dikonversi MySQL menjadi 1 atau 0 saat baris dibaca kembali.

Dua driver client-server kini telah kita kendalikan, dan keduanya berulang kali menyinggung satu frasa yang sama: parameter terikat. Frasa itu adalah garis batas antara aplikasi yang selamat dan aplikasi yang bisa dibongkar orang luar lewat input jahat. Saatnya kita bedah mengapa dan bagaimana — pada Chapter Query Parameterized.