iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Vibe Coding

Vibe Coding的30天,自然語言與AI共舞,從Prompt到高品質原型落地系列 第 15

Day 15|資料庫建模Prisma ORM與PostgreSQL Schema設計

  • 分享至 

  • xImage
  •  

在Day14中,我們使用了Next.jsRouteHandlers與Zod建立了具備強型別防禦與統一Response格式的API端點。然而,當時API底層依然是用記憶體陣列(skillsDb)來模擬資料寫入。

今天(Day15),我們將正式告別記憶體陣列,踏入真實資料庫Persistence(持久化)的領域!

我們將選擇Node.js/TypeScript生態系中最受歡迎的ORM套件——Prisma,搭配PostgreSQL資料庫,引導AI進行資料庫Schema建模、關聯宣告、資料型別映射,並執行資料庫Migration!

1.為什麼選擇Prisma+PostgreSQL?
在VibeCoding的架構中,PrismaORM擁有幾項無可比擬的優勢:

單一真理來源(SingleSourceofTruth):只需要在schema.prisma中定義一次模型,Prisma就會自動生成完整的TypeScriptClient、資料庫MigrationSQL與型別宣告。

與Zod/TypeScript完美契合:PrismaClient生成的型別可以直接與我們在Day14寫的Zod驗證層與前端Component共享。

直觀的聲明式語法(DeclarativeSchema):連LLMAI都極度擅長撰寫與重構.prisma檔案。

實戰步驟1:安裝Prisma與初始化資料庫設定
步驟A:安裝套件
在Terminal執行:

npm install @prisma/client
npm install -D prisma

步驟B:初始化Prisma
執行以下指令產生prisma/schema.prisma與.env檔:

npx prisma init

這會在.env中產生資料庫連線字串範例:

DATABASE_URL="postgresql://postgres:password@localhost:5432/vibepulse?schema=public"

3.實戰步驟2:請AI撰寫prisma/schema.prisma
開啟Cursor,對著@prisma/schema.prisma發送Prompt:

@lib/validations/skill.ts(參考型別與枚舉宣告)
@mocks/skillsData.ts(參考原始資料結構)
你是一位資深的DatabaseArchitect。請幫我為VibePulse設計`prisma/schema.prisma`。

需求細節:
1.Datasource&Generator:
-provider="postgresql"
-generatorclient="prisma-client-js"
2.Enum定義:
-`Category`:`FRONTEND`,`BACKEND`,`AI`,`DEVOPS`
-`Status`:`LEARNING`,`MASTERED`,`PLANNED`
3.SkillModel(資料表`skills`):
-`id`:String(UUID,`@id@default(uuid())`)
-`title`:String
-`category`:Category(Enum)
-`proficiency`:Int(`@default(0)`)
-`tags`:String[](PostgreSQL原生Array支援)
-`status`:Status(`@default(LEARNING)`)
-`notesCount`:Int(`@default(0)`)
-`lastPracticedAt`:DateTime(`@default(now())`)
-`createdAt`:DateTime(`@default(now())`)
-`updatedAt`:DateTime(`@updatedAt`)
4.效能優化(Indexes):
-為`category`與`status`欄位建立單獨或複合索引(`@@index`),以加速未來的查詢效能。
-為`@map("skills")`設定資料表底層映射名稱。

AI產出的prisma/schema.prisma:

// prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

enum Category {
  FRONTEND
  BACKEND
  AI
  DEVOPS
}

enum Status {
  LEARNING
  MASTERED
  PLANNED
}

model Skill {
  id              String   @id @default(uuid())
  title           String
  category        Category
  proficiency     Int      @default(0)
  tags            String[] @default([])
  status          Status   @default(LEARNING)
  notesCount      Int      @default(0)
  lastPracticedAt DateTime @default(now())
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  @@index([category])
  @@index([status])
  @@map("skills")
}

4.實戰步驟3:執行Migration與建立資料庫單例(lib/prisma.ts)
步驟A:執行首次Migration
確保PostgreSQL資料庫啟動後,在Terminal執行:

npx prisma migrate dev --name init_skill_table

Prisma會自動在prisma/migrations目錄下生成標準SQL並建置skills資料表!

步驟B:建立PrismaClient單例(Singleton)
在Next.js的開發環境(HMR熱重載)中,如果不將PrismaClient寫成單例,可能會因為多次instantiation導致資料庫連線池(ConnectionPool)耗盡。

請AI建立@lib/prisma.ts:

// lib/prisma.ts
import { PrismaClient } from '@prisma/client';

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
  });

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;

5.實戰步驟4:寫入SeedData(將MockData遷移至PostgreSQL)
為了讓資料庫一開始就有資料測試,我們請AI撰寫一隻SeedScriptprisma/seed.ts:

@mocks/skillsData.ts
@prisma/schema.prisma

請幫我撰寫 `prisma/seed.ts` 腳本,將 `mocks/skillsData.ts` 中的假資料寫入 PostgreSQL 資料庫。

需求細節:
1. 先執行 `prisma.skill.deleteMany()` 清空舊資料。
2. 將 `mockSkills` 的字串 Enum (如 'Frontend') 轉譯為 Schema 中的的大寫 Enum (如 'FRONTEND')。
3. 使用 `prisma.skill.createMany()` 批量寫入。
4. 在 `package.json` 中加入 `"prisma": { "seed": "ts-node prisma/seed.ts" }` 的設定指引。

執行Seed腳本:

npx prisma db seed

Terminal顯示:

Seeding database...
Created 5 skills in PostgreSQL successfully!

今天我們完成了VibePulse資料持久化架構的重磅升級:

使用聲明式語法完成了prisma/schema.prisma的PostgreSQL建模。

建立了完整的Enum、Index索引與Migration檔案。

封裝了避免連線洩漏的PrismaClientSingleton,並完成SeedData導入!


上一篇
Day 14|Next.js Route Handlers實作用Zod驗證Request Body與Error Handling
下一篇
Day 16|將Route Handlers與Prisma ORM徹底串接CRUD完整落地
系列文
Vibe Coding的30天,自然語言與AI共舞,從Prompt到高品質原型落地16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言