-
Notifications
You must be signed in to change notification settings - Fork 11
Prisma Guide
- Introduction
- Installation
- Essential Prisma Commands
- Prisma Schema
- Data Modeling
- Prisma Migrations
- Prisma Client
Prisma is a next-generation ORM (Object-Relational Mapping) that simplifies database workflows for application developers. It consists of three main tools:
- Prisma Client: Auto-generated and type-safe query builder for Node.js & TypeScript
- Prisma Migrate: Declarative data modeling & migration system
- Prisma Studio: GUI to view and edit data in your database
Install Prisma and Prism Client: Prisma Client is an auto-generated database client that's tailored to your database schema
yarn add prisma --dev
yarn add @prisma/client
-
Initialize Prisma in your project:
npx prisma init
This creates a
prisma
directory with aschema.prisma
file and a.env
file. -
Generate Prisma Client after schema changes:
npx prisma generate
This updates the Prisma Client API based on your schema.
-
Create and apply a migration:
npx prisma migrate dev --name init
This creates a new migration based on your schema changes and applies it to your database.
-
Open Prisma Studio (GUI to view and edit data):
npx prisma studio
The Prisma schema file (schema.prisma
) is the main configuration file for your Prisma setup. It contains three main parts:
- Data source: Specifies your database connection
- Generator: Indicates that you want to generate Prisma Client
- Data model: Defines your application models
Example:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
In your schema.prisma
file, you can define various types of relations between models.
Foreign key relations in Prisma are defined using the @relation
attribute.
model User {
id String @id @default(uuid())
firstName String?
lastName String?
email String? @unique
systemAdmin SystemAdmin? @relation("systemAdmin")
}
model SystemAdmin {
id String @id @default(uuid())
role String @default("admin")
user User @relation(name: "systemAdmin", fields: [userId], references: [id])
userId String @unique
}
Explanation:
- The
@relation
attribute establishes the foreign key relation betweenUser
andSystemAdmin
. -
fields: [userId]
specifies thatuserId
inSystemAdmin
holds the foreign key. -
references: [id]
indicates thatuserId
references theid
field inUser
. - The
@unique
constraint onuserId
ensures a one-to-one relationship. - The
name: "systemAdmin"
parameter gives a name to this specific relation, which is useful when you have multiple relations between the same models.
A one-to-one relation means that one record in a model is associated with exactly one record in another model.
model User {
id String @id @default(uuid())
systemAdmin SystemAdmin? @relation("systemAdmin")
}
model SystemAdmin {
id String @id @default(uuid())
user User @relation(name: "systemAdmin", fields: [userId], references: [id])
userId String @unique
}
Explanation:
- Each
User
can have at most oneSystemAdmin
profile. - Each
SystemAdmin
belongs to exactly oneUser
. - The
@unique
constraint onuserId
in theSystemAdmin
model ensures the one-to-one relationship. - The
?
afterSystemAdmin
in theUser
model makes it optional, allowing users without admin privileges.
In a one-to-many relation, one record in a model can be associated with multiple records in another model.
model User {
id String @id @default(uuid())
processes Process[]
}
model Process {
id String @id @default(uuid())
name String
owner User? @relation(fields: [ownerId], references: [id], onDelete: Cascade)
ownerId String
}
Explanation:
- The
User
model has aprocesses
field of typeProcess[]
, indicating that a user can have multiple processes. - The
Process
model has anowner
field and anownerId
field for the foreign key. - The
@relation
inProcess
establishes the many-to-one relationship withUser
. - The
onDelete: Cascade
option means that if aUser
is deleted, all associatedProcess
records will also be deleted.
A many-to-many relation allows multiple records in one model to be associated with multiple records in another model.
model User {
id String @id @default(uuid())
memberIn Membership[]
}
model Space {
id String @id @default(uuid())
name String?
members Membership[]
}
model Membership {
id String @id @default(uuid())
userId String
environmentId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
space Space @relation(fields: [environmentId], references: [id], onDelete: Cascade)
}
Explanation:
- This is an example of a many-to-many relation implemented with an explicit join model (
Membership
). - A
User
can be a member of multipleSpace
s, and aSpace
can have multipleUser
members. - The
Membership
model serves as a join table, connectingUser
andSpace
. - Both
User
andSpace
have a field referencing an array ofMembership
. - The
Membership
model has foreign keys to bothUser
andSpace
. - The
onDelete: Cascade
option ensures that when aUser
orSpace
is deleted, the correspondingMembership
records are also deleted.
Self-relations are used when a model needs to reference itself, typically to represent hierarchical data structures.
model Folder {
id String @id @default(uuid())
name String
description String
parentFolder Folder? @relation("parent-child", fields: [parentId], references: [id], onDelete: Cascade)
parentId String?
childrenFolder Folder[] @relation("parent-child")
space Space @relation(fields: [environmentId], references: [id], onDelete: Cascade)
environmentId String
processes Process[]
}
Explanation:
- This
Folder
model has a self-relation to represent a folder hierarchy. - The
parentFolder
field references anotherFolder
, representing the parent folder. -
parentId
is the foreign key that stores the ID of the parent folder. - The
childrenFolder
field is an array ofFolder
, representing subfolders. - Both
parentFolder
andchildrenFolder
use the same relation name "folderChildren", creating a two-way relationship. -
parentId
is optional (String?), allowing for top-level folders that don't have a parent. - The
onDelete: Cascade
option means that when a parent folder is deleted, all its subfolders are also deleted.
Prisma Migrate helps you manage database schemas: Once you have created or made any changes to the schema, apply it to the db
-
Create a migration:
npx prisma migrate dev --name init
-
Apply migrations to your database:
npx prisma migrate deploy
Prisma Client is an auto-generated, type-safe query builder.
-
Generate Prisma Client:
npx prisma generate
-
Use Prisma Client in your code:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
// use `prisma` in your application to read and write data in your DB
Here are some basic CRUD operations using Prisma Client:
// Create
const newUser = await prisma.user.create({
data: {
email: 'alice@prisma.io',
name: 'Alice',
},
})
// Read
const user = await prisma.user.findUnique({
where: {
email: 'alice@prisma.io',
},
select: {
name:true
}
})
// Update
const updatedUser = await prisma.user.update({
where: {
email: 'alice@prisma.io',
},
data: {
name: 'Alicia',
},
})
// Delete
const deletedUser = await prisma.user.delete({
where: {
email: 'alice@prisma.io',
},
})
For more detailed information, always refer to the official Prisma documentation.
This is the Dev Wiki