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 Safety | Otomatis menghasilkan tipe TypeScript dari schema database — zero runtime error karena tipe yang salah |
| Auto-generated Client | Prisma Client di-generate dari schema, sehingga autocomplete dan dokumentasi selalu akurat |
| Declarative Schema | Schema ditulis dalam satu file .prisma yang mudah dibaca dan dikelola |
| Visual Database Browser | Prisma Studio menyediakan GUI untuk melihat dan mengedit data di database |
| Multi-database | Mendukung PostgreSQL, MySQL, SQLite, SQL Server, MongoDB, dan CockroachDB |
| Migration System | Sistem migrasi yang kuat untuk mengelola perubahan skema database secara terkontrol |
Prisma vs ORM Lain
| Aspek | Prisma | Sequelize | TypeORM |
|---|---|---|---|
| Definisi Schema | File .prisma khusus | JavaScript class | Decorator TypeScript |
| Type Safety | 🟢 Otomatis | 🟡 Manual | 🟢 Sebagian |
| Learning Curve | 🟢 Mudah | 🟡 Sedang | 🟡 Sedang |
| Query Builder | Prisma Client | Query API | QueryBuilder / Repository |
| Migrations | Built-in otomatis | Manual / CLI | Manual / CLI |
| Popularity (2026) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
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
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.
// 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
// 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
// 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
// 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
// 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
`;
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: