tutorial, express.js,

Koneksi Database di Express.js dengan Prisma ORM

Kiki/🎮🍉⌨️🍩💻 Kiki/🎮🍉⌨️🍩💻 Aug 24, 2026 · 9 mins read
Koneksi Database di Express.js dengan Prisma ORM
Share this

API yang menyimpan data di memori (in-memory) akan kehilangan semua data setiap kali server restart. Untuk aplikasi nyata, kita butuh database yang persisten. Di artikel ini kita akan menghubungkan Express.js ke database menggunakan Prisma — ORM (Object-Relational Mapper) modern untuk Node.js yang sangat developer-friendly.

Kita akan menggunakan SQLite sebagai database agar mudah dicoba tanpa setup server database terpisah, namun konsep yang sama berlaku untuk PostgreSQL dan MySQL.


Apa itu Prisma?

Prisma adalah ORM generasi berikutnya untuk Node.js dan TypeScript. Keunggulannya:

  • Type-safe — autocomplete dan error saat kompilasi (terutama dengan TypeScript)
  • Migrasi otomatis — ubah schema, Prisma urus migrasi database
  • Prisma Studio — GUI visual untuk melihat dan mengedit data
  • Mendukung PostgreSQL, MySQL, SQLite, SQL Server, MongoDB

Setup Project

mkdir express-prisma
cd express-prisma
npm init -y
npm install express prisma @prisma/client
npx prisma init --datasource-provider sqlite

Perintah prisma init menghasilkan:

  • Folder prisma/ dengan file schema.prisma
  • File .env dengan DATABASE_URL

Definisikan Schema

Edit prisma/schema.prisma:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model Pengguna {
  id         Int       @id @default(autoincrement())
  nama       String
  email      String    @unique
  password   String
  dibuatPada DateTime  @default(now())
  artikel    Artikel[]
}

model Artikel {
  id         Int      @id @default(autoincrement())
  judul      String
  konten     String
  kategori   String   @default("umum")
  diterbitkan Boolean  @default(false)
  dibuatPada DateTime @default(now())
  diubahPada DateTime @updatedAt
  penulis    Pengguna @relation(fields: [penulisId], references: [id])
  penulisId  Int
}

Jalankan migrasi untuk membuat tabel di database:

npx prisma migrate dev --name init

Generate Prisma Client:

npx prisma generate

Buat Prisma Client Instance

prisma/client.js:

const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
module.exports = prisma;

Route CRUD dengan Prisma

routes/artikel.js:

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

// GET /artikel
router.get('/', async (req, res, next) => {
  try {
    const { kategori, q, halaman = 1, limit = 10 } = req.query;
    const skip = (parseInt(halaman) - 1) * parseInt(limit);

    const where = {};
    if (kategori) where.kategori = kategori;
    if (q) where.judul = { contains: q };

    const [data, total] = await Promise.all([
      prisma.artikel.findMany({
        where,
        skip,
        take: parseInt(limit),
        orderBy: { dibuatPada: 'desc' },
        include: { penulis: { select: { id: true, nama: true } } }
      }),
      prisma.artikel.count({ where })
    ]);

    res.json({ total, halaman: parseInt(halaman), data });
  } catch (err) {
    next(err);
  }
});

// GET /artikel/:id
router.get('/:id', async (req, res, next) => {
  try {
    const artikel = await prisma.artikel.findUnique({
      where: { id: parseInt(req.params.id) },
      include: { penulis: { select: { id: true, nama: true, email: true } } }
    });

    if (!artikel) return res.status(404).json({ error: 'Artikel tidak ditemukan' });
    res.json(artikel);
  } catch (err) {
    next(err);
  }
});

// POST /artikel
router.post('/', async (req, res, next) => {
  try {
    const { judul, konten, kategori, penulisId } = req.body;
    if (!judul || !konten || !penulisId) {
      return res.status(422).json({ error: 'Judul, konten, dan penulisId wajib diisi' });
    }

    const baru = await prisma.artikel.create({
      data: { judul, konten, kategori: kategori || 'umum', penulisId: parseInt(penulisId) }
    });
    res.status(201).json(baru);
  } catch (err) {
    next(err);
  }
});

// PATCH /artikel/:id
router.patch('/:id', async (req, res, next) => {
  try {
    const diupdate = await prisma.artikel.update({
      where: { id: parseInt(req.params.id) },
      data: req.body
    });
    res.json(diupdate);
  } catch (err) {
    if (err.code === 'P2025') {
      return res.status(404).json({ error: 'Artikel tidak ditemukan' });
    }
    next(err);
  }
});

// DELETE /artikel/:id
router.delete('/:id', async (req, res, next) => {
  try {
    await prisma.artikel.delete({ where: { id: parseInt(req.params.id) } });
    res.status(204).send();
  } catch (err) {
    if (err.code === 'P2025') {
      return res.status(404).json({ error: 'Artikel tidak ditemukan' });
    }
    next(err);
  }
});

module.exports = router;

Entry Point Lengkap

index.js:

const express = require('express');
const prisma = require('./prisma/client');
const app = express();

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

// Error handler
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Terjadi kesalahan server' });
});

// Graceful shutdown — tutup koneksi Prisma saat app berhenti
process.on('SIGINT', async () => {
  await prisma.$disconnect();
  process.exit(0);
});

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

Prisma Studio — GUI Visual

Untuk melihat dan mengedit data secara visual, jalankan:

npx prisma studio

Browser akan terbuka di http://localhost:5555 dengan antarmuka tabel yang bisa kamu gunakan untuk membaca, menambah, dan menghapus data.


Migrasi Saat Schema Berubah

Ketika kamu mengubah schema.prisma (misalnya menambah kolom baru), jalankan:

npx prisma migrate dev --name tambah-kolom-slug

Prisma akan otomatis membuat file migrasi SQL dan menerapkannya ke database.


Kesimpulan

Prisma membuat interaksi dengan database menjadi sangat menyenangkan di Express.js — tidak ada query SQL manual, tidak ada hasil berupa raw array, dan semua operasi async/await yang bersih. Dengan schema yang terdefinisi jelas dan migrasi otomatis, pengelolaan database menjadi jauh lebih mudah.

Di artikel berikutnya, kita tambahkan lapisan keamanan dengan autentikasi JWT di Express.js.

Kiki/🎮🍉⌨️🍩💻
Written by Kiki/🎮🍉⌨️🍩💻
hello I'm friend K.