☀️Siang
Database

Prisma ORM: Database Modern untuk JavaScript

Tutorial lengkap belajar Prisma ORM dari nol — schema definition, migrations, CRUD operations, relasi antar tabel, filtering, sorting, transaksi, dan best practices

Artikel: Prisma Orm Artikel: Prisma Orm


1. Pengenalan Prisma ORM

Prisma adalah Object-Relational Mapping (ORM) modern untuk JavaScript dan TypeScript yang dirancang untuk membuat interaksi dengan database menjadi lebih mudah, aman, dan efisien. Berbeda dengan ORM tradisional seperti Sequelize atau TypeORM, Prisma menggunakan pendekatan schema-first dengan bahasa definisi tersendiri yang disebut Prisma Schema Language (PSL).

Prisma pertama kali dirilis oleh Prisma Labs pada tahun 2019 dan dengan cepat menjadi salah satu ORM paling populer di ekosistem Node.js. Dukungan terhadap TypeScript yang sangat baik menjadikannya pilihan utama untuk proyek-proyek modern.

Mengapa Memilih Prisma?

Keunggulan Penjelasan
Type SafetyOtomatis menghasilkan tipe TypeScript dari schema database — zero runtime error karena tipe yang salah
Auto-generated ClientPrisma Client di-generate dari schema, sehingga autocomplete dan dokumentasi selalu akurat
Declarative SchemaSchema ditulis dalam satu file .prisma yang mudah dibaca dan dikelola
Visual Database BrowserPrisma Studio menyediakan GUI untuk melihat dan mengedit data di database
Multi-databaseMendukung PostgreSQL, MySQL, SQLite, SQL Server, MongoDB, dan CockroachDB
Migration SystemSistem migrasi yang kuat untuk mengelola perubahan skema database secara terkontrol

Prisma vs ORM Lain

Aspek Prisma Sequelize TypeORM
Definisi SchemaFile .prisma khususJavaScript classDecorator TypeScript
Type Safety🟢 Otomatis🟡 Manual🟢 Sebagian
Learning Curve🟢 Mudah🟡 Sedang🟡 Sedang
Query BuilderPrisma ClientQuery APIQueryBuilder / Repository
MigrationsBuilt-in otomatisManual / CLIManual / CLI
Popularity (2026)⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Diagram: Arsitektur Prisma

APLIKASI ANDA

Prisma Client (Generated)

• Type-safe database queries

• Autocomplete & IntelliSense

• Query engine yang dioptimasi

💡 Tips

Prisma bukan pengganti SQL sepenuhnya. Untuk query yang sangat kompleks, Prisma menyediakan fitur $queryRaw dan $executeRaw untuk menulis raw SQL secara langsung.



2. Instalasi dan Setup

Untuk memulai menggunakan Prisma, kita perlu menginstal paket Prisma di proyek Node.js yang sudah ada. Pastikan Anda sudah memiliki Node.js versi 16 atau lebih baru.

Inisialisasi Proyek

Diagram: Relasi Antar Model
Relasi Antar Model

User id (PK) email (UQ) nama umur ◄ one-to-many...

Profile id (PK) bio avatar userId (FK) ▼ ▼ Post...

Tag id (PK) nama (UQ)



7. Filtering dan Sorting

Prisma menyediakan API filtering yang sangat kaya dan ekspresif. Anda bisa menggunakan berbagai operator seperti equals, contains, gt, lt, in, dan banyak lagi.

TypeScript — Filtering
// Filter dasar
const activeUsers = await prisma.user.findMany({
  where: { isActive: true },
});

// Filter dengan operator perbandingan
const dewasa = await prisma.user.findMany({
  where: {
    umur: {
      gte: 18,    // Greater than or equal
      lte: 60,    // Less than or equal
    },
  },
});

// Filter dengan string operator
const cariUser = await prisma.user.findMany({
  where: {
    nama: {
      contains: 'Budi',     // Mengandung kata "Budi"
      mode: 'insensitive',  // Tidak case-sensitive
    },
  },
});

// Filter dengan operator IN
const userTertentu = await prisma.user.findMany({
  where: {
    id: { in: [1, 3, 5, 7] },
  },
});

// Filter dengan NOT
const nonActive = await prisma.user.findMany({
  where: {
    NOT: { isActive: true },
  },
});

// Filter kombinasi AND / OR
const complexFilter = await prisma.user.findMany({
  where: {
    AND: [
      { isActive: true },
      {
        OR: [
          { umur: { gte: 25 } },
          { nama: { startsWith: 'Admin' } },
        ],
      },
    ],
  },
});

// Filter relasi
const postsDariUserAktif = await prisma.post.findMany({
  where: {
    author: {
      isActive: true,
    },
    published: true,
  },
  include: {
    author: {
      select: { nama: true, email: true },
    },
  },
});

Sorting dan Pagination

TypeScript — Sorting & Pagination
// Sorting ascending
const ascUsers = await prisma.user.findMany({
  orderBy: { nama: 'asc' },
});

// Sorting descending
const descUsers = await prisma.user.findMany({
  orderBy: { createdAt: 'desc' },
});

// Multiple sorting
const sorted = await prisma.user.findMany({
  orderBy: [
    { umur: 'asc' },
    { nama: 'desc' },
  ],
});

// Cursor-based pagination (lebih efisien untuk data besar)
const cursorPagination = await prisma.user.findMany({
  take: 10,
  skip: 1, // Skip cursor
  cursor: {
    id: 50, // Mulai dari ID 50
  },
  orderBy: { id: 'asc' },
});

// Aggregation — count, avg, sum, min, max
const stats = await prisma.post.aggregate({
  _count: true,
  _avg: { authorId: true },
  where: { published: true },
});

// GroupBy
const groupByAuthor = await prisma.post.groupBy({
  by: ['authorId'],
  _count: true,
  where: { published: true },
  having: {
    authorId: { gt: 0 },
  },
});


8. Transaksi (Transactions)

Dalam pengembangan aplikasi nyata, sering kali kita perlu melakukan beberapa operasi database secara bersamaan — semuanya berhasil atau semuanya gagal. Prisma menyediakan dua cara untuk melakukan transaksi: Interactive Transactions dan Batch Transactions.

Batch Transactions

TypeScript — Batch Transaction
// Batch transaction — semua operasi dijalankan bersamaan
const [user, post] = await prisma.$transaction([
  prisma.user.create({
    data: {
      email: 'transaksi@example.com',
      nama: 'User Transaksi',
    },
  }),
  prisma.post.create({
    data: {
      judul: 'Post dari Transaksi',
      konten: 'Dibuat dalam transaksi yang sama',
      authorId: 1,
    },
  }),
]);
console.log('User:', user.nama);
console.log('Post:', post.judul);

Interactive Transactions

TypeScript — Interactive Transaction
// Interactive transaction — bisa menjalankan logic di tengah transaksi
async function transferPost(authorFromId: number, authorToId: number, postId: number) {
  const result = await prisma.$transaction(async (tx) => {
    // 1. Cek apakah post milik authorFrom
    const post = await tx.post.findUnique({
      where: { id: postId },
    });

    if (!post || post.authorId !== authorFromId) {
      throw new Error('Post tidak ditemukan atau bukan milik author ini');
    }

    // 2. Update author post
    const updatedPost = await tx.post.update({
      where: { id: postId },
      data: { authorId: authorToId },
    });

    // 3. Catat log transfer
    const log = await tx.logTransfer.create({
      data: {
        postId,
        fromAuthorId: authorFromId,
        toAuthorId: authorToId,
      },
    });

    return { updatedPost, log };
  });

  return result;
}

// Contoh penggunaan
try {
  const result = await transferPost(1, 2, 10);
  console.log('Transfer berhasil:', result);
} catch (error) {
  console.error('Transfer gagal:', error.message);
}

Raw SQL Queries

TypeScript — Raw SQL
// Query raw SQL
const users = await prisma.$queryRaw`
  SELECT * FROM "User" WHERE "isActive" = true ORDER BY "createdAt" DESC
`;

// Raw SQL dengan parameter (mencegah SQL injection)
const userId = 1;
const user = await prisma.$queryRaw`
  SELECT * FROM "User" WHERE "id" = ${userId}
`;

// Execute raw SQL (untuk INSERT, UPDATE, DELETE)
await prisma.$executeRaw`
  UPDATE "User" SET "isActive" = false WHERE "umur" < 18
`;
⚠️ Keamanan Raw SQL

Selalu gunakan template literal dengan parameter (${parameter}) saat menggunakan raw SQL. Jangan pernah menggabungkan string secara manual karena rentan terhadap SQL Injection. Prisma otomatis meng-escape parameter yang diberikan melalui template literal.



9. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Prisma ORM:

Pertanyaan 1: Apa file utama yang digunakan Prisma untuk mendefinisikan model database?

a) schema.json
b) schema.prisma
c) models.ts
d) database.yaml

Pertanyaan 2: Perintah apa yang digunakan untuk membuat dan menjalankan migrasi di environment development?

a) prisma migrate deploy
b) prisma migrate dev
c) prisma db push
d) prisma generate

Pertanyaan 3: Bagaimana cara mengambil data beserta relasinya dalam Prisma?

a) Menggunakan metode .populate()
b) Menggunakan opsi include atau select
c) Menulis SQL JOIN manual
d) Menggunakan decorator @Include

Pertanyaan 4: Apa fungsi dari Prisma Client yang di-generate dari schema?

a) Mengelola migrasi database
b) Menyediakan API type-safe untuk operasi CRUD
c) Membuat UI untuk database
d) Menggantikan SQL sepenuhnya

Pertanyaan 5: Metode mana yang digunakan untuk melakukan transaksi interaktif di Prisma?

a) prisma.transaction()
b) prisma.$transaction(async (tx) => { ... })
c) prisma.begin()
d) prisma.execute()
🔍 Zoom
100%
🎨 Tema