Operasi CRUD dengan Prisma Client

Operasi CRUD dengan Prisma Client

Saatnya jadi dalang data! Pelajari cara melakukan operasi CRUD (Create, Read, Update, Delete) ke database Anda menggunakan metode-metode yang disediakan oleh Prisma Client, lengkap dengan contoh query dan opsi-opsi penting.

Jadi Dalang Data: Operasi CRUD Pake Prisma Client yang Asyik!

Udah punya "penerjemah" Prisma Client yang siap ngobrol sama databasemu? Keren! Sekarang, saatnya kita jadi "dalang" yang ngatur data di "panggung" database kita. Kita bakal belajar cara ngelakuin empat operasi paling fundamental yang jadi tulang punggung hampir semua aplikasi: CRUD.

CRUD itu singkatan dari:

  • Create (Membuat data baru)
  • Read (Membaca/Mengambil data yang udah ada)
  • Update (Mengubah/Memperbarui data yang udah ada)
  • Delete (Menghapus data)

Prisma Client nyediain metode-metode yang intuitif dan type-safe buat ngelakuin semua operasi ini. Kita bakal pake contoh model User dan Post yang udah kita definisiin di schema.prisma sebelumnya.

Ingat: Semua operasi Prisma Client yang berinteraksi sama database itu asinkron (asynchronous). Jadi, kita bakal sering pake async/await buat nanganinnya.

typescripttypescript
// Jangan lupa impor dan inisialisasi Prisma Client-mu dulu
// Biasanya di file terpisah (misal, src/lib/prisma.ts)
// import { PrismaClient } from '@prisma/client';
// const prisma = new PrismaClient();
// Untuk contoh di bawah, kita asumsikan 'prisma' sudah jadi instance PrismaClient.

1. Create (Membuat Data Baru)

Buat nambahin record baru ke tabel, kita pake metode .create().

  • Sintaks Dasar: await prisma.namaModel.create({ data: { ...objekDataBaru } });
    • namaModel: Nama modelmu dengan huruf kecil pertama (misal, user, post).
    • data: Objek yang isinya field dan nilai buat record baru itu. Strukturnya harus cocok sama model di skemamu!

Contoh Membuat User Baru:

typescripttypescript
async function buatUserBaru() {
  try {
    const userBaru = await prisma.user.create({
      data: {
        email: "budi.prisma@example.com",
        nama: "Budi Prismawan",
        password: "passwordyangsudahdihash", // Di aplikasi nyata, password harus di-hash!
        // createdAt dan updatedAt biasanya otomatis diisi (kalau ada @default atau @updatedAt)
      },
    });
    console.log("User baru berhasil dibuat:", userBaru);
    return userBaru;
  } catch (error) {
    console.error("Gagal membuat user:", error);
  }
}
// buatUserBaru();

Contoh Membuat Post Baru yang Berelasi dengan User: Kalau mau bikin post yang terhubung ke user tertentu, kita bisa pake connect di dalem data.

typescripttypescript
async function buatPostBaru(idAuthor: number, judulPost: string, kontenPost?: string) {
  try {
    const postBaru = await prisma.post.create({
      data: {
        judul: judulPost,
        konten: kontenPost, // Ini opsional karena di skema kita 'konten String?'
        dipublikasi: true,
        author: { // Ini cara ngonekin ke User yang udah ada
          connect: {
            id: idAuthor // Sambungin ke User dengan ID ini
          }
        }
        // Atau kalau mau langsung ngasih authorId-nya juga bisa:
        // authorId: idAuthor 
        // (tapi pake 'connect' lebih idiomatik Prisma buat relasi)
      },
    });
    console.log("Post baru berhasil dibuat:", postBaru);
    return postBaru;
  } catch (error) {
    console.error("Gagal membuat post:", error);
  }
}
// buatPostBaru(1, "Belajar Prisma Itu Menyenangkan!"); // Asumsi user dengan ID 1 udah ada

2. Read (Membaca/Mengambil Data)

Prisma nyediain beberapa metode buat ngambil data, tergantung kebutuhanmu.

a. findMany(): Ambil Banyak Record (Bisa Semua atau Difilter)

  • Sintaks Dasar: await prisma.namaModel.findMany({ ...opsiQuery });
  • Ngembaliin array dari objek record. Kalau gak ada yang cocok, array-nya kosong.
  • Opsi Query yang Sering Dipake di findMany() (dan metode find lainnya):
    • where: Buat filter record berdasarkan kondisi.
      • Contoh: { email: "budi@example.com" }, { poin: { gt: 100 } } (gt = greater than).
    • select: Buat milih field apa aja yang mau diambil.
      • Contoh: { select: { id: true, email: true, nama: false } } (ambil id & email aja, nama gak usah).
    • include: Buat ngambil data dari model lain yang berelasi.
      • Contoh: { include: { posts: true } } (ambil user beserta semua post-nya).
    • orderBy: Buat ngurutin hasil.
      • Contoh: { orderBy: { createdAt: 'desc' } } (urutin berdasarkan createdAt, terbaru dulu).
    • take: Buat ngambil sejumlah record tertentu (limit).
    • skip: Buat ngelompati sejumlah record tertentu (offset, buat pagination).

Contoh findMany():

typescripttypescript
async function ambilSemuaUser() {
  const users = await prisma.user.findMany();
  console.log("Semua User:", users);
}
 
async function ambilUserDenganPost() {
  const usersDenganPosts = await prisma.user.findMany({
    include: {
      posts: true, // Ambil juga semua post milik user ini
    },
  });
  usersDenganPosts.forEach(user => {
    console.log(`User: ${user.nama}`);
    user.posts.forEach(post => {
      console.log(`  - Post: ${post.judul}`);
    });
  });
}
 
async function ambilPostYangDipublikasi() {
  const postsPublik = await prisma.post.findMany({
    where: { dipublikasi: true },
    orderBy: { createdAt: 'desc' },
    select: { judul: true, createdAt: true } // Cuma ambil judul dan tanggal dibuat
  });
  console.log("Post Publik:", postsPublik);
}
// ambilSemuaUser();
// ambilUserDenganPost();
// ambilPostYangDipublikasi();

b. findUnique(): Ambil Satu Record Berdasarkan Field Unik (ID atau @unique)

  • Sintaks Dasar: await prisma.namaModel.findUnique({ where: { fieldUnik: nilai } });
  • Ngembaliin satu objek record kalau ketemu, atau null kalau gak ketemu.
  • Wajib pake field yang udah ditandain @id atau @unique di skemamu.

Contoh findUnique():

typescripttypescript
async function ambilUserById(idUser: number) {
  const user = await prisma.user.findUnique({
    where: {
      id: idUser,
    },
    include: { posts: true } // Bisa juga include relasi
  });
  if (user) {
    console.log("User ditemukan:", user);
  } else {
    console.log(`User dengan ID ${idUser} tidak ditemukan.`);
  }
}
// ambilUserById(1);
// ambilUserById(99); // Harusnya null

c. findFirst(): Ambil Record Pertama yang Cocok Sama Kondisi

  • Sintaks Dasar: await prisma.namaModel.findFirst({ where: { ...kondisi }, ...opsiLain });
  • Mirip findMany tapi cuma ngembaliin satu objek record pertama yang cocok, atau null.
  • Berguna kalau kamu cuma butuh satu contoh data yang cocok, gak peduli ada berapa banyak.

3. Update (Mengubah Data yang Udah Ada)

Buat ngupdate record yang udah ada.

a. update(): Update Satu Record Spesifik

  • Sintaks Dasar: await prisma.namaModel.update({ where: { fieldUnik: nilai }, data: { ...perubahan } });
  • Wajib pake where buat nunjukin record mana yang mau diupdate (berdasarkan field unik).
  • data isinya field dan nilai baru yang mau di-set.
  • Ngembaliin objek record yang udah diupdate.

Contoh update():

typescripttypescript
async function updateNamaUser(idUser: number, namaBaru: string) {
  try {
    const userDiupdate = await prisma.user.update({
      where: { id: idUser },
      data: { nama: namaBaru }, // Cuma field 'nama' yang diupdate
    });
    console.log("User berhasil diupdate:", userDiupdate);
  } catch (error) {
    // Error bisa terjadi kalau record dengan ID itu gak ada
    console.error(`Gagal update user ID ${idUser}:`, error);
  }
}
// updateNamaUser(1, "Budi Sanjaya Putra");

b. updateMany(): Update Banyak Record Sekaligus yang Cocok Kondisi

  • Sintaks Dasar: await prisma.namaModel.updateMany({ where: { ...kondisi }, data: { ...perubahan } });
  • Ngembaliin objek yang isinya properti count (jumlah record yang ke-update).
  • Hati-hati: updateMany gak ngejalanin middleware atau beberapa validasi level aplikasi yang mungkin ada di update tunggal.

Contoh updateMany():

typescripttypescript
async function publikasikanSemuaDraftPost() {
  const hasilUpdate = await prisma.post.updateMany({
    where: { dipublikasi: false }, // Semua post yang belum dipublikasi
    data: { dipublikasi: true },   // Jadiin true
  });
  console.log(`${hasilUpdate.count} post berhasil dipublikasikan.`);
}
// publikasikanSemuaDraftPost();

c. upsert(): Update Kalau Ada, Create Kalau Gak Ada

  • Sintaks Dasar: await prisma.namaModel.upsert({ where: { fieldUnik: nilai }, update: { ...perubahan }, create: { ...dataBaru } });
  • Dia bakal nyoba nyari record pake where.
    • Kalau ketemu, dia ngejalanin bagian update.
    • Kalau gak ketemu, dia ngejalanin bagian create.
  • Super berguna biar gak perlu ngecek manual "udah ada belum ya datanya?"

4. Delete (Menghapus Data)

Buat ngapus record. HATI-HATI! Operasi hapus ini biasanya permanen!

a. delete(): Hapus Satu Record Spesifik

  • Sintaks Dasar: await prisma.namaModel.delete({ where: { fieldUnik: nilai } });
  • Wajib pake where buat nunjukin record mana yang mau dihapus.
  • Ngembaliin objek record yang baru aja dihapus.

Contoh delete():

typescripttypescript
async function hapusUser(idUser: number) {
  try {
    const userDihapus = await prisma.user.delete({
      where: { id: idUser },
    });
    console.log("User berhasil dihapus:", userDihapus);
  } catch (error) {
    console.error(`Gagal menghapus user ID ${idUser}:`, error);
  }
}
// hapusUser(2); // Hapus user dengan ID 2 (kalau ada)

Kalau user itu punya post yang berelasi dan gak ada aturan cascading delete di skemamu, ini bisa error.

b. deleteMany(): Hapus Banyak Record Sekaligus yang Cocok Kondisi

  • Sintaks Dasar: await prisma.namaModel.deleteMany({ where: { ...kondisi } });
  • Ngembaliin objek yang isinya count (jumlah record yang kehapus).
  • Kalau where dikosongin ({}), dia bakal NGAPUS SEMUA RECORD di tabel itu! SUPER HATI-HATI!

Contoh deleteMany() (Pake dengan sangat waspada):

typescripttypescript
async function hapusSemuaPostDraft() {
  const hasilHapus = await prisma.post.deleteMany({
    where: { dipublikasi: false }, // Hapus semua post yang statusnya draft
  });
  console.log(`${hasilHapus.count} post draft berhasil dihapus.`);
}
// hapusSemuaPostDraft();
 
// JANGAN JALANIN INI KECUALI KAMU BENERAN MAU NGOSONGIN TABEL USER!!!
// async function hapusSemuaUser() {
//   const hasil = await prisma.user.deleteMany({});
//   console.log(`${hasil.count} user dihapus.`);
// }

Dengan metode-metode CRUD dari Prisma Client ini (create, findMany, findUnique, update, delete, dll.), kamu udah bisa ngelakuin hampir semua operasi database dasar yang dibutuhin aplikasi. Dan yang paling enak, semuanya type-safe dan auto-complete-nya jalan kalau kamu pake TypeScript!

Jangan ragu buat nyoba-nyoba semua query ini di proyek latihanmu. Liat gimana hasilnya, dan gimana opsi-opsi kayak where, select, include bisa ngebantu kamu ngambil data persis seperti yang kamu mau.

Uji Pemahamanmu!

Memeriksa status login...