今天要來教大家簡單起一個 prisma
專案讓大家感受一下什麼叫做 type safe
的 ORM
~
先產生一個資料夾,然後進入 folder
> mkdir hello-prisma
> cd hello-prisma
初始化 package
然後安裝相關 lib
> npm init -y
> npm install typescript ts-node @types/node --save-dev
初始化 typescript setting
> npx tsc --init
然後 install prisma
> npm install prisma --save-dev
最後 prisma
也需要做初始化,這邊選用 sqlite
當作我們的 datasource
> npx prisma init --datasource-provider sqlite
上面的 cli
會自動幫我們產生 prisma
的資料夾,提供我們訂定 model
的 schema
,然後因為我們是使用 SQL lite
也會自動幫我們設定好 SQLite
的 database
之後我們先到 prisma/schema.prisma
中去定義我們的 Model
// prisma/schema.prisma
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
}
Models
在 prisma
中有以下的功用:
database
中的 table
prisma client
提供 code generate
的基礎配置別忘記每當我們有新增 Model
時候要記得跑一次 Migration
不然 Database
並不會知道我們定好的 Model
> npx prisma migrate dev --name init
migration cli
做了三件事:
SQL migration file
在 prisma/migrations
資料夾。SQL migration
到 database
。prisma generate
針對 model
去產生對應的 prisma client api
取使用,同時自動產生 type
。你會看到 migration
自動執行 prisma generate
就是會在你的 node_modules
透過 code generate
產生對應 prisma client
的 inteface
以及各種 Model
的 type
,這也是為什麼 prisma
可以做到 type safe
的原因,所以如果你的 node_modules
不小心刪掉,記得要重新跑一下 prisma generate
喔~
然後 prisma
也會多一個 .env
去 link
你的 dataSource
,那因為我們是用 sqlite
prisma
會自動幫我們產生 dev.db
所以這邊的 DATABASE_URL
會 link
到 dev.db
位置
// .env
DATABASE_URL="file:./dev.db"
首先先創建 index.ts
然後使用 PrismaClient
去創建一個 prisma client
的 instance
,然後每次當我們使用 PrismaClient
背後都會自動起一個 connection
到 database
,所以記得要在 than
或是 error
時候去釋放 connection
喔~
// index.ts
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
// ... you will write your Prisma Client queries here
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
那因為 prisma client
有自動幫我們 code generate
了,所以 user Model
也會自動有對應欄位的 type
。
然後至邊眼睛很利的小夥伴應該看到,我們這邊使用 faker
這套 lib
去自動幫我們產生 mock data
,對於不想思考內容的朋友應該有方長大的幫助~有興趣的讀者可以自行玩玩看~ Faker
import { PrismaClient } from "@prisma/client";
import { faker } from '@faker-js/faker';
const prismaClient = new PrismaClient()
async function main() {
const user = await prismaClient.user.create({
data: {
name: faker.person.fullName(),
email: faker.internet.email()
}
})
console.log(user)
}
然後直接 run
我們的 index.ts
> npx ts-node index.ts
如此就成功 create
一筆 record
了~
{ id: 1, email: 'alice@prisma.io', name: 'Alice' }
現在成功寫入 Data
接下來就教大家怎麼 get
,我們直接改用其他 api
findMany
這樣就可以拿到全部的 users
內容了。
async function main() {
const users = await prisma.user.findMany()
console.log(users)
}
這樣我們就成功拿到資料拉~
[{ id: 1, email: 'alice@prisma.io', name: 'Alice' }]
另一個 prisma
的特點是,他提供關聯式的用法,還記得我們的 Post
是關聯到 User
的嗎,接下來就教讀者如何在 create
的時候去 relaction
其他的 Model
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
}
這邊稍微改寫一下我們 create
的使用方式,如以下的 posts
因為他跟 User
是一對多的關係,所以我們在 User
的 create data
欄位中 posts
是可以 create
多筆的。
async function main() {
const user = await prisma.user.create({
data: {
name: 'Bob',
email: 'bob@prisma.io',
posts: {
create: [
{
title: 'Hello World',
published: true
},
{
title: 'My second post',
content: 'This is still a draft'
}
],
},
},
})
console.log(user)
}
上面的 create
是在於 User
跟 Post
都沒有資料情況下一邊 create
一邊做關聯的,如果 posts
已經存在可以使用 connect
然後對應到 postId
const users = await prismaClient.user.create({
data: {
name: faker.person.fullName(),
email: faker.internet.email(),
posts: {
connect: [{ id: 1 }, { id: 2 }]
}
}
})
這時你會發現並沒有 log
跟 user
有關聯的 post data
,那是因為 prisma
預設只要跟 relaction
有關的 query
,如果不是透過 include
的方式,並不會 log
出來,接下來我們就來學習 include
的用法。
{ id: 2, email: 'bob@prisma.io', name: 'Bob' }
我們先修改之前的 read
,現在只需要加上 include
然後告訴 prisma
哪些 relaction
的 Model
需要顯示。
async function main() {
const usersWithPosts = await prisma.user.findMany({
include: {
posts: true,
},
})
console.dir(usersWithPosts, { depth: null })
}
執行 index.ts
後你就會看到完整的內容了
[
{ id: 1, email: 'alice@prisma.io', name: 'Alice', posts: [] },
{
id: 2,
email: 'bob@prisma.io',
name: 'Bob',
posts: [
{
id: 1,
title: 'Hello World',
content: null,
published: true,
authorId: 2
},
{
id: 2,
title: 'My second post',
content: 'This is still a draft',
published: false,
authorId: 2
}
]
}
]
補充一個比較特別的是如果只是需要隱藏特定的 fields
可以用 select
的語法,甚至也可以用到特定的關聯式資料
const usersWithPosts = await prismaClient.user.findMany({
select: {
id: true,
email: true,
name: true,
posts: {
select: {
id: true,
title: true
}
}
}
})
結果大概是這個樣子
[
{
id: 2,
email: "Jalen_Padberg59@hotmail.com",
name: "Everett Graham",
posts: [
{
id: 1,
title: "amo-verto-voco",
}, {
id: 2,
title: "demo-uxor-corona",
}
],
}
]
今天內容大致到這邊感謝各位讀者耐心的觀看~
✅ 前端社群 :
https://lihi3.cc/kBe0Y