這次的鐵人賽想跟大家分享一套自己在平常開發中很常用到的一套 ORM
就是 prisma
,會想用他的原因是因為,去年鐵人賽在介紹 TRPC
的時候有用到 prisma
,但一直沒有更深入的去理解它,那今年我們就來完成筆者的心願吧~接下來的 30 天會再好好的跟大家補齊一些你不知道的 prisma
功能,就請大家好好期待一下~
大致上先簡單列出,目前筆者覺得 prisma
的優勢,之後也會一一跟大家介紹以下的內容~
auto generate type
plugin
雖然目前市面上很多 ORM
也符合下面的優勢,例如 drizzle
他也是一套有強大的 type safe
的 ORM
甚至 DX
也不輸給 prisma
筆者其實也很喜歡 XD ,但還是想先整理一下 prisma
筆記哈哈,如果讀者有興趣可以來對我指教~
在學習 ORM
之前筆者先簡單介紹一下使用 ORM
的優勢與好處~如圖所見, ORM
就是一層 DB
跟 Client
的中介層,注意一下這邊的 Client
並不是 front end
中 user
使用的 client
,這邊得 client
指的是 application
的部分,也就是你在哪邊使用 prisma client
的 api
,因為 primsa
可以使用的地方,除了 backend application
甚至還可以用在 serverless applications
和 microservices
等等,所以這邊才會泛指 client
~ 那因為我們的 client
有非常多種的內容,所以可能會遇到的點是,在不同的 client
端點中,每次都要寫一些重複性的 SQL
指令而且還要考慮不同 client
中是否能順利的連到 DB
,所以對開法者來說,如果有一套 tool
可以涵蓋所有的內容,同時簡化 DB
語法的話,對於整體的開法效率也會大大提升~於是 ORM
得概念就出現了,但同時 ORM
就會遇到一個問題是,因為他要對 DB
的操作去做映射,所以對 SQL
語法的支援度就相當重要,所以這也是在技術選型時,要考量的其中一個因素。
這邊想補充一點就是 primsa
支援使用原生 SQL
的指令,例如以下的 queryRaw
或是 executeRaw
等等,所以如果你發現有些 DB
中能沒有支援在 prisma
使用時,也可以當做備用方案~
const email = 'emelie@prisma.io'
const result = await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`
const result: number =
await prisma.$executeRaw`UPDATE User SET active = true WHERE emailValidated = true`
這邊要介紹 ORM
中最重要的一個部分就是定 schema
, primsa
很厲害的地方就是它同時支援 SQL
以及 NoSQL
,甚至對於不同 SQL
中有不同的 Schema
訂定的方式~
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
posts Post[]
}
上面的 schema
可以簡單分成三個部分介紹。
DB connection
以及你的 DB type
。prisma
怎麼去生成你的 prisma client
。db
的 models
。prisma
除了可以訂新的 models
外,也可以同步已存在的 models
到你的 prisma schema
中,只要打以下的 cli
。
> npx prisma db pull
然後你就會發現你的 schema
就多了一些原本 db
的 models
了~
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
在 prisma
中如果你需要表達關聯式,可以透過 @relation
、[]
來表達是一對一、一對多,或是多對多的關係。
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
posts Post[]
}
prisma
因為是一套有 type safe
的 ORM
,所以每次做完 DB pull
或是 DB migration
後,prisma
都會在你 local
的 node_modules
中自動產生所有你需要的 type
。
如果 DB
需要添加新的欄位可以直接在 schema
中加上。
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
phone String? // add new filed
}
之後跑 migration cli
就會跑出下列的訊息,然後會要求你描述這次 migration
的 name
有點像是 git
在提交 commit
一樣。
> npx prisma migrate dev
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
? Enter a name for the new migration: › add phone fields in User modal
然後 prisma
就會跟你你提交的 name
自動在你的 migration
加新的folder
✔ Enter a name for the new migration: … add phone fields in User modal
Applying migration `20240907043004_add_phone_fields_in_user_modal`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20240907043004_add_phone_fields_in_user_modal/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (v5.19.1) to ./node_modules/@prisma/client in 51ms
然後仔細觀察 migrations folder
就會記錄每次 migration
的紀錄,主要是產生原生 SQL
指令。
prisma
很貼心的提供 studio
去查看專案中用到的所有 model
,首先先打下方的 cli
。
> npx prisma studio
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Prisma Studio is up on http://localhost:5555
然後打開 http://localhost:5555
,你會看到這邊記錄著可以用到的 model
。
然後點進去各自的 model
會看到會用到的欄位有哪些,以及目前有哪些資料,那因為還沒有加資料,所以內容會是空的。
然後你也可以直接在 studio
中直接加資料。
加完之後我們可以簡單測試拿資料。
import { PrismaClient } from "@prisma/client";
const prismaClient = new PrismaClient()
const main = async () => {
const userLists = await prismaClient.user.findMany()
console.log(userLists)
}
main()
你會發現你在 studio
加的 data
,也成功不再在你的 client
了。
[
{
id: 1,
email: "some@gmail.com",
name: "Danny",
phone: null,
}
]
今天大致上先初探 prisma
的內容,明天我們繼續介紹,為何你需要用 prisma
,感謝各位讀者的觀看我們明天見~
✅ 前端社群 :
https://lihi3.cc/kBe0Y