Desain Skema Prisma
Saatnya merancang 'cetakan' databasemu! Pelajari sintaks Prisma Schema Language (PSL) untuk mendefinisikan model data (tabel), field, tipe data, atribut field (seperti ID, default, unik), dan relasi antar model.
Jadi Arsitek Database: Rancang Model Datamu Pake Prisma Schema!
Udah berhasil nyiapin "toko" Prisma di proyekmu dengan prisma init
? Keren! Sekarang, kita bakal jadi arsitek yang ngerancang "ruangan-ruangan" dan "perabotan" di dalem "toko data" kita. Di Prisma, semua rancangan ini kita tuangin ke dalem satu file utama: prisma/schema.prisma
.
File schema.prisma
ini adalah jantung dari penggunaan Prisma. Di sinilah kamu bakal ngedefinisiin:
- Sumber Data (Datasource): Database apa yang kamu pake dan gimana cara nyambungnya. (Ini udah kita sentuh sedikit pas setup SQLite).
- Generator Klien (Client Generator): Ngasih tau Prisma buat nge-generate Prisma Client yang type-safe.
- Model Data (Data Models): Ini yang paling penting! Model data ini ngewakilin tabel-tabel di databasemu, kolom-kolom (field) di tiap tabel, tipe data tiap kolom, dan hubungan (relasi) antar tabel.
Kita bakal nulis semua ini pake bahasa khusus yang simpel dan gampang dibaca namanya Prisma Schema Language (PSL).
Ngintip Lagi schema.prisma
Kita
Buka file prisma/schema.prisma
yang udah di-generate sebelumnya. Isinya kurang lebih kayak gini (kalau kita udah ubah ke SQLite):
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite" // Kita udah set ini ke sqlite
url = env("DATABASE_URL") // Ngambil dari file .env
}
// Model-model data kita bakal ditulis di bawah sini
generator client { ... }
: Bagian ini ngasih tau Prisma buat nge-generate Prisma Client dalam bahasa JavaScript (yang bisa dipake di TypeScript juga). Prisma Client ini yang nanti kita pake di kode aplikasi kita buat ngobrol sama database.datasource db { ... }
: Bagian ini ngedefinisiin koneksi ke database kita.provider = "sqlite"
: Kita pake SQLite. Bisa jugapostgresql
,mysql
, dll.url = env("DATABASE_URL")
: String koneksi diambil dari variabelDATABASE_URL
di file.env
kita (yang udah kita set kefile:./dev.db
ataufile:./prisma/dev.db
).
Mendesain Model Data: "Cetakan" Tabelmu
Sekarang bagian paling serunya: bikin Model. Di PSL, satu model
itu biasanya ngewakilin satu tabel di database relasionalmu.
- Sintaks Dasar Model:
prisma
model NamaModel { namaField1 TipeData1 @atributField1 @atributField2 namaField2 TipeData2 // Properti tanpa atribut juga bisa // ... field lain ... // Untuk relasi (dibahas nanti) // namaRelasi NamaModelRelasi @relation(...) }
model NamaModel
: Keywordmodel
diikuti nama modelmu (biasanya diawali huruf besar dan pake PascalCase, misalUser
,ProductOrder
). Nama model ini bakal jadi nama tabel di database (Prisma bisa ngatur konvensi penamaan tabelnya, misal jadiusers
atauproduct_orders
).namaField TipeData
: Tiap baris di dalem model ngedefinisiin satu field (kolom) beserta tipe datanya.namaField
: Nama kolom (biasanya camelCase, misalfirstName
,createdAt
).TipeData
: Tipe data buat kolom itu.
Tipe Data Dasar di Prisma Schema Language (PSL)
PSL punya tipe data dasar yang bakal nge-map ke tipe data spesifik di databasemu:
String
: Buat teks (VARCHAR, TEXT, dll. tergantung database).Int
: Buat angka integer (INT, INTEGER).BigInt
: Buat angka integer yang gede banget.Float
: Buat angka desimal (FLOAT, REAL, DOUBLE).Decimal
: Buat angka desimal dengan presisi tinggi (DECIMAL, NUMERIC), cocok buat data keuangan.Boolean
: Buat nilaitrue
ataufalse
(BOOLEAN, BIT).DateTime
: Buat nyimpen tanggal dan waktu (TIMESTAMP, DATETIME).Json
: Buat nyimpen data JSON langsung di satu kolom (JSON, JSONB di PostgreSQL).Bytes
: Buat data biner.
Modifier Tipe:
?
(Opsional): Tambahin?
setelah tipe data buat nandain kalau field itu bolehNULL
(opsional, gak wajib diisi). Contoh:deskripsi String?
[]
(List/Array): Tambahin[]
setelah tipe data buat nandain kalau field itu adalah array/list dari tipe tersebut. Penting: Gak semua database ngedukung tipe array secara native di kolom. Prisma bisa nyimulasiin ini, tapi perilakunya tergantung provider database. (Misal,String[]
di PostgreSQL itu array beneran, di MySQL mungkin jadi JSON atau cara lain).
Atribut Field (@
dan @@
)
Selain nama dan tipe, field juga bisa punya atribut buat ngasih "sifat" atau "aturan" tambahan. Atribut field diawali satu @
, atribut level model (blok) diawali dua @@
.
Beberapa atribut field yang paling sering dipake:
@id
: Nandain kalau field itu adalah Primary Key buat tabel/model itu. Biasanya dipake di fieldid
.@default(nilai_atau_fungsi)
: Nentuin nilai default buat field itu kalau gak diisi pas bikin data baru.- Contoh:
status String @default("pending")
,createdAt DateTime @default(now())
,poin Int @default(0)
,uuid String @default(uuid())
(butuh fungsiuuid()
dari database atau Prisma).
- Contoh:
@unique
: Nandain kalau nilai di field itu harus unik di seluruh tabel (gak boleh ada yang sama). Cocok buat email, username.@updatedAt
: Otomatis ngeset field (yang tipenyaDateTime
) ke waktu saat ini setiap kali record itu di-update. Berguna buat ngelacak kapan data terakhir diubah.@map("nama_kolom_di_db")
: Kalau kamu mau nama field di model Prismamu beda sama nama kolom di database benerannya.@relation(...)
: Ini dipake buat ngedefinisiin relasi antar model. Bakal kita bahas lebih detail.
Contoh Model User
dan Post
Sederhana:
// prisma/schema.prisma
// ... (generator dan datasource masih sama) ...
model User {
id Int @id @default(autoincrement()) // Primary Key, auto-increment (beda per DB)
email String @unique // Email harus unik
nama String? // Nama boleh kosong (opsional)
password String // Password wajib ada (nantinya di-hash ya!)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi: Satu User bisa punya banyak Post
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
judul String
konten String?
dipublikasi Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi: Satu Post dimiliki oleh satu User
author User @relation(fields: [authorId], references: [id])
authorId Int // Foreign Key ke tabel User
}
Bedah Contoh:
-
User
Model:id
: TipeInt
, jadi Primary Key (@id
), dan nilainya di-generate otomatis sama database pas data baru dibuat (@default(autoincrement())
). (Sintaks autoincrement bisa beda dikit antar database, misaluuid()
buat ID string unik).email
:String
, wajib unik.nama
:String
, opsional (?
).createdAt
:DateTime
, otomatis diisi waktu saat ini pas User dibuat.updatedAt
:DateTime
, otomatis diupdate tiap kali User diubah.posts Post[]
: Ini field relasi. Nunjukin kalau satuUser
bisa punya banyak ([]
) record dari modelPost
. Prisma pinter, dia bakal ngerti ini relasi one-to-many.
-
Post
Model:id
,judul
,konten
,dipublikasi
,createdAt
,updatedAt
: Mirip kayak di User.author User @relation(fields: [authorId], references: [id])
: Ini juga field relasi.author User
: Nunjukin kalau satuPost
itu "milik" satuUser
.@relation(...)
: Ngasih detail soal relasinya.fields: [authorId]
: Ngasih tau Prisma kalau fieldauthorId
di modelPost
ini yang jadi foreign key.references: [id]
: Ngasih tau Prisma kalauauthorId
itu ngacunya ke fieldid
di modelUser
.
authorId Int
: Ini field foreign key benerannya yang nyimpenid
dariUser
pemilik post ini. Tipe datanya harus sama kayakid
diUser
.
Dengan ngedefinisiin relasi kayak gini, Prisma Client nanti bakal ngasih kita cara gampang buat ngambil data user beserta semua post-nya, atau sebaliknya.
Mendesain Relasi Lebih Lanjut
Prisma ngedukung semua jenis relasi database umum:
-
One-to-One (1-1): Misal, satu
User
punya satuProfile
.prisma
model User { id Int @id @default(autoincrement()) profile Profile? // Profile opsional, dan unik per User } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique // userId di Profile harus unik, nandain 1-1 }
-
One-to-Many (1-N): Udah kita liat di contoh
User
danPost
. Satu User -> Banyak Post. Satu Post -> Satu User. -
Many-to-Many (N-M): Misal, satu
Post
bisa punya banyakCategory
, dan satuCategory
bisa dipake di banyakPost
.- Cara Implisit (Prisma yang bikinin tabel join):
prisma
model Post { id Int @id @default(autoincrement()) judul String categories Category[] // Post punya banyak Category } model Category { id Int @id @default(autoincrement()) nama String @unique posts Post[] // Category dipake di banyak Post } // Prisma bakal otomatis bikin tabel join di belakang layar (_CategoryToPost)
- Cara Eksplisit (Kita definisiin tabel join-nya sendiri): Kadang kita butuh nambahin info ekstra di tabel join (misal, tanggal kapan post ditambahin ke kategori).
prisma
model Post { id Int @id @default(autoincrement()) judul String kategoriDiPost KategoriDiPost[] // Ngacu ke model tabel join } model Category { id Int @id @default(autoincrement()) nama String @unique postDiKategori KategoriDiPost[] // Ngacu ke model tabel join } model KategoriDiPost { // Ini model tabel join-nya post Post @relation(fields: [postId], references: [id]) postId Int kategori Category @relation(fields: [kategoriId], references: [id]) kategoriId Int ditugaskanPada DateTime @default(now()) // Info tambahan di tabel join @@id([postId, kategoriId]) // Primary key gabungan }
- Cara Implisit (Prisma yang bikinin tabel join):
Milih antara implisit atau eksplisit buat many-to-many tergantung kebutuhan. Kalau gak butuh field ekstra di tabel join, implisit lebih simpel.
Atribut Level Model (Blok) @@
Selain atribut field (@
), ada juga atribut yang diterapin ke seluruh model (blok), diawali dua @@
.
@@id([...])
: Buat bikin composite primary key (primary key yang terdiri dari beberapa field).@@unique([...])
: Buat bikin composite unique constraint (kombinasi beberapa field harus unik).@@index([...])
: Buat nambahin indeks database ke beberapa field (buat percepat query).@@map("nama_tabel_di_db")
: Kalau mau nama model beda sama nama tabel di database.
Contoh di model KategoriDiPost
tadi: @@id([postId, kategoriId])
.
File schema.prisma
ini adalah "cetak biru" buat seluruh struktur databasemu. Dengan Prisma Schema Language (PSL) yang deklaratif dan gampang dibaca, kamu bisa ngedesain model data dan relasinya dengan jelas.