iT邦幫忙

2024 iThome 鐵人賽

DAY 3
1
Modern Web

一些讓你看來很強的 ORM - prisma系列 第 3

Day03. 一些讓你看來很強的 ORM - prisma (專案建置)

  • 分享至 

  • xImage
  •  

今天要來教大家簡單起一個 prisma 專案讓大家感受一下什麼叫做 type safeORM

Add Project Root

先產生一個資料夾,然後進入 folder

> mkdir hello-prisma
> cd hello-prisma

Install

初始化 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 的資料夾,提供我們訂定 modelschema ,然後因為我們是使用 SQL lite 也會自動幫我們設定好 SQLitedatabase
https://ithelp.ithome.com.tw/upload/images/20240917/20145677hjPuVAGjkP.png

Model data

之後我們先到 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
}


Modelsprisma 中有以下的功用:

  • 對應 database 中的 table
  • 作為 prisma client 提供 code generate 的基礎配置

Migration

別忘記每當我們有新增 Model 時候要記得跑一次 Migration 不然 Database 並不會知道我們定好的 Model

> npx prisma migrate dev --name init

migration cli 做了三件事:

  • 新增 SQL migration fileprisma/migrations 資料夾。
  • 執行 SQL migrationdatabase
  • 在背景執行 prisma generate 針對 model 去產生對應的 prisma client api 取使用,同時自動產生 type

https://ithelp.ithome.com.tw/upload/images/20240917/20145677GjlJ1SJ5xp.png

你會看到 migration 自動執行 prisma generate 就是會在你的 node_modules 透過 code generate 產生對應 prisma clientinteface 以及各種 Modeltype ,這也是為什麼 prisma 可以做到 type safe 的原因,所以如果你的 node_modules 不小心刪掉,記得要重新跑一下 prisma generate 喔~

https://ithelp.ithome.com.tw/upload/images/20240917/20145677BaZR33ecVh.png

然後 prisma 也會多一個 .envlink 你的 dataSource ,那因為我們是用 sqlite prisma 會自動幫我們產生 dev.db 所以這邊的 DATABASE_URLlinkdev.db 位置

// .env
DATABASE_URL="file:./dev.db"

Create data

首先先創建 index.ts 然後使用 PrismaClient 去創建一個 prisma clientinstance ,然後每次當我們使用 PrismaClient 背後都會自動起一個 connectiondatabase ,所以記得要在 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' }

Read Data

現在成功寫入 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' }]

Relation database

另一個 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 是一對多的關係,所以我們在 Usercreate 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 是在於 UserPost 都沒有資料情況下一邊 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 }]
      }
    }
  })

這時你會發現並沒有 loguser 有關聯的 post data,那是因為 prisma 預設只要跟 relaction 有關的 query ,如果不是透過 include 的方式,並不會 log 出來,接下來我們就來學習 include 的用法。

{ id: 2, email: 'bob@prisma.io', name: 'Bob' }

我們先修改之前的 read ,現在只需要加上 include 然後告訴 prisma 哪些 relactionModel 需要顯示。

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


上一篇
Day02. 一些讓你看來很強的 ORM - prisma (比較)
下一篇
Day04. 一些讓你看來很強的 ORM - prisma (zeabur)
系列文
一些讓你看來很強的 ORM - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言