最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用Next.js?+?Prisma?+?MySQL開發(fā)全棧項(xiàng)目

 更新時(shí)間:2026年03月24日 08:24:11   作者:我的刀盾  
在Next.js項(xiàng)目的任何地方都可以使用Prisma來訪問數(shù)據(jù)庫,Prisma提供了豐富的查詢方法,滿足您在項(xiàng)目中的各種需求,這篇文章主要介紹了如何使用Next.js+Prisma+MySQL開發(fā)全棧項(xiàng)目的相關(guān)資料,需要的朋友可以參考下

本文介紹如何用 Next.jsPrisma、MySQL 搭建全棧應(yīng)用:包含 MySQL 與 MySQL Workbench 的安裝與基本使用、創(chuàng)建項(xiàng)目、目錄含義、數(shù)據(jù)庫建模、Migrations(遷移) 的工作方式與命令,并附代碼示例。

一、技術(shù)棧分工

技術(shù)作用
Next.jsReact 框架:路由、SSR、服務(wù)端組件、Route Handlers(API)
PrismaORM:類型安全查詢、Schema 定義、遷移版本管理
MySQL關(guān)系型數(shù)據(jù)庫:表、外鍵、事務(wù)、索引

二、如何創(chuàng)建 Next.js 項(xiàng)目

2.1 前置條件

  • 已安裝 Node.js(建議 LTS 版本)
  • 包管理器任選:npm、pnpmyarn

2.2 使用官方腳手架

在項(xiàng)目父目錄執(zhí)行:

npx create-next-app@latest my-app

交互式選項(xiàng)說明(根據(jù)版本可能略有差異):

選項(xiàng)建議說明
TypeScriptYes與 Prisma、大型項(xiàng)目更匹配
ESLintYes統(tǒng)一代碼風(fēng)格
Tailwind CSS按需UI 快速開發(fā)可選用
src/ directory按需若選 Yes,應(yīng)用代碼在 src/app
App RouterYes當(dāng)前推薦,與本文目錄說明一致
Turbopack按需開發(fā)時(shí)可選更快的打包器

進(jìn)入項(xiàng)目并安裝依賴:

cd my-app
npm install

2.3 本地運(yùn)行

npm run dev

瀏覽器訪問 http://localhost:3000。默認(rèn)端口為 3000。

2.4 常用腳本(package.json)

命令作用
npm run dev開發(fā)模式,熱更新
npm run build生產(chǎn)構(gòu)建
npm run start啟動(dòng)生產(chǎn)構(gòu)建后的服務(wù)(需先 build
npm run lint運(yùn)行 ESLint

三、典型目錄與文件說明(App Router)

以下以 未使用 src/ 的默認(rèn)結(jié)構(gòu)為例;若創(chuàng)建時(shí)選了 src/,則把 app、components 等放在 src/ 下即可。

my-app/
├── app/                      # App Router:頁面、布局、路由
│   ├── layout.tsx            # 根布局(全局 HTML 殼、字體、Provider)
│   ├── page.tsx              # 路由 "/" 的首頁
│   ├── globals.css           # 全局樣式
│   ├── loading.tsx           # 可選:該路由段的加載 UI(Suspense)
│   ├── error.tsx             # 可選:該路由段的錯(cuò)誤邊界
│   └── api/                  # Route Handlers(HTTP API)
│       └── users/
│           └── route.ts      # 對(duì)應(yīng)路徑 /api/users
├── public/                   # 靜態(tài)資源:favicon、圖片等,URL 根路徑直接訪問
├── prisma/
│   ├── schema.prisma         # 數(shù)據(jù)模型與數(shù)據(jù)庫連接配置
│   └── migrations/           # 遷移歷史(由 prisma migrate 生成,勿手改 SQL 邏輯)
├── lib/                      # 常用:工具函數(shù)、Prisma 單例等(自建)
│   └── prisma.ts
├── components/               # 可復(fù)用 UI 組件(自建)
├── .env                      # 本地環(huán)境變量(勿提交密鑰)
├── .env.example              # 環(huán)境變量示例(可提交)
├── next.config.ts / .js      # Next 構(gòu)建與運(yùn)行時(shí)配置
├── tsconfig.json             # TypeScript 配置
└── package.json

3.1app/目錄

  • page.tsx:該路由的頁面 UI;文件夾名即 URL 路徑段。
  • layout.tsx:嵌套布局,子路由共享外殼(導(dǎo)航欄、側(cè)邊欄等)。
  • route.ts:只處理 HTTP 方法(GET、POST 等),不渲染頁面,用于 REST API。
  • 默認(rèn)導(dǎo)出為 Server Component,可直接 async 并訪問數(shù)據(jù)庫;需要瀏覽器事件、hooks 時(shí)在文件頂部加 "use client"。

3.2public/

放不需要經(jīng)過打包處理的靜態(tài)文件,例如 public/logo.png 對(duì)應(yīng)訪問路徑 /logo.png。

3.3prisma/

  • schema.prisma:定義數(shù)據(jù)源、生成器、Model(表結(jié)構(gòu))。
  • migrations/:每次執(zhí)行 prisma migrate dev(或生產(chǎn)用 deploy)產(chǎn)生的遷移記錄,見下文「Migrations 詳解」。

3.4 根目錄配置文件

  • next.config.*:圖片域名、重定向、實(shí)驗(yàn)特性等。
  • tsconfig.json:路徑別名(如 @/*)常在這里配置,與 import 有關(guān)。

四、MySQL 安裝與 MySQL Workbench

4.1 官方下載地址

以下均為 Oracle MySQL 官方站點(diǎn),請(qǐng)從 Downloads 中選擇操作系統(tǒng)與安裝包類型。

軟件說明下載頁
MySQL Community Server數(shù)據(jù)庫服務(wù)本體(必裝,供本地/服務(wù)器運(yùn)行 MySQL)dev.mysql.com/downloads/m…
MySQL Installer(僅 Windows)一站式安裝器,可勾選 Server、Workbench、Shell 等dev.mysql.com/downloads/i…
MySQL Workbench圖形化管理與 SQL 開發(fā)工具(可選但強(qiáng)烈推薦)dev.mysql.com/downloads/w…

說明

  • 若使用 MySQL Installer for Windows,通常一次勾選 MySQL Server + MySQL Workbench 即可,無需單獨(dú)下載 Workbench。
  • macOS 可使用官網(wǎng) DMG 或包管理器(如 Homebrew:brew install mysql);Linux 常用發(fā)行版?zhèn)}庫或官網(wǎng) APT/YUM 倉庫,Workbench 可單獨(dú)安裝。

4.2 在 Windows 上安裝 MySQL Server(常見流程)

以下以 MySQL Installer 為例(適合本機(jī)開發(fā)):

  1. 打開 MySQL Installer 下載頁,選擇 Windows (x86, 64-bit), MSI Installer(體積較大的完整安裝包或在線安裝包均可)。
  2. 運(yùn)行安裝程序,選擇安裝類型:
    • Developer Default:會(huì)安裝 Server、Workbench、Shell 等,適合開發(fā)。
    • 若只需數(shù)據(jù)庫服務(wù),可選 Server only。
  3. 按向?qū)?zhí)行 Execute 安裝所選組件。
  4. Type and Networking 中保持默認(rèn)端口 3306(除非端口沖突,需與 Prisma 的 DATABASE_URL 一致)。
  5. Authentication 中保持默認(rèn) Strong Password(推薦)。
  6. 設(shè)置 root 用戶密碼并牢記;后續(xù) Workbench、Prisma 連接都會(huì)用到。
  7. 將 MySQL 配置為 Windows Service,并勾選 Start the MySQL Server at System Startup(開機(jī)自啟,便于開發(fā))。
  8. 完成安裝。

4.3 安裝后如何確認(rèn) MySQL 已運(yùn)行

  • 服務(wù):按 Win + R,輸入 services.msc,查找 MySQLMySQL80 等服務(wù)名,狀態(tài)應(yīng)為 正在運(yùn)行
  • 命令行(若安裝時(shí)勾選了命令行客戶端且已加入 PATH):
mysql --version
  • 若無法直接執(zhí)行 mysql,可在「開始菜單」打開 MySQL Command Line Client,用 root 密碼登錄測(cè)試。

4.4 安裝 MySQL Workbench

  • 若已通過 MySQL Installer 勾選 Workbench,可跳過單獨(dú)安裝。
  • 否則打開 Workbench 下載頁,選擇 Windows / macOS / Linux 對(duì)應(yīng)安裝包,按向?qū)О惭b即可。

4.5 使用 MySQL Workbench 連接數(shù)據(jù)庫

  1. 打開 MySQL Workbench。
  2. 主界面 MySQL Connections 區(qū)域點(diǎn)擊 「+」MySQL Connections 旁的加號(hào),新建連接。
  3. 填寫連接參數(shù)(本地開發(fā)常見值):
字段典型值說明
Connection Name任意名稱,如 Local Dev僅顯示用
Hostname127.0.0.1localhost本機(jī)數(shù)據(jù)庫
Port3306與安裝時(shí)一致
Usernameroot或你創(chuàng)建的其他用戶
Password點(diǎn)擊 Store in Keychain / Vault… 保存密碼,避免每次輸入
  1. 點(diǎn)擊 Test Connection,提示成功即可 OK 保存。
  2. 雙擊該連接進(jìn)入主工作區(qū):左側(cè)為 Navigator(庫表列表),中間為 SQL 編輯與結(jié)果區(qū)。

4.6 MySQL Workbench 基本操作

操作步驟
創(chuàng)建數(shù)據(jù)庫(Schema)左側(cè) Schemas 面板空白處右鍵 → Create Schema… → 輸入庫名(如 mydb)→ Apply;或在 Query 窗口執(zhí)行:CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
執(zhí)行 SQL頂部 File → New Query Tab 或工具欄新建查詢標(biāo)簽 → 輸入 SQL → 選中語句 → 點(diǎn)擊 閃電圖標(biāo) 執(zhí)行(或 Ctrl + Enter)。
查看表數(shù)據(jù)Schemas 中展開數(shù)據(jù)庫 → Tables → 表名右鍵 → Select Rows - Limit 1000。
查看表結(jié)構(gòu)表名右鍵 → Table InspectorAlter Table
新建用戶/授權(quán)(進(jìn)階)菜單 Server → Users and Privileges(需相應(yīng)權(quán)限);開發(fā)階段常用 root,生產(chǎn)環(huán)境應(yīng)使用最小權(quán)限賬號(hào)。

與Prisma配合時(shí):先在 Workbench 里創(chuàng)建空庫(如mydb),再在項(xiàng)目.env中把DATABASE_URL指向該庫;表結(jié)構(gòu)通常交給prisma migrate管理,無需在 Workbench 里手工建每張表(除非你不用遷移、純手寫 SQL)。

五、接入 Prisma 與 MySQL

5.1 安裝

npm install prisma @prisma/client
npx prisma init

prisma init 會(huì)創(chuàng)建 prisma/schema.prisma,并在項(xiàng)目根目錄提示創(chuàng)建 .env

5.2 配置連接串(.env)

DATABASE_URL="mysql://用戶名:密碼@主機(jī):3306/數(shù)據(jù)庫名"

示例(本地 MySQL):

DATABASE_URL="mysql://root:secret@localhost:3306/mydb"

注意:將 .env 加入 .gitignore,倉庫中只保留 .env.example(不含真實(shí)密碼)。

5.3schema.prisma示例

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

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

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  published Boolean  @default(false)
  authorId  Int
  author    User     @relation(fields: [authorId], references: [id])
  createdAt DateTime @default(now())
}

5.4 生成 Client

修改 schema 后執(zhí)行:

npx prisma generate

會(huì)依據(jù)當(dāng)前 schema.prisma 生成 node_modules/.prisma/client 等,供 TypeScript 使用。

六、Migrations(數(shù)據(jù)庫遷移)詳解

Migration 指:把「數(shù)據(jù)庫結(jié)構(gòu)應(yīng)該怎樣」從 Prisma Schema 出發(fā),變成 可重復(fù)執(zhí)行、可版本控制 的 SQL 變更步驟。團(tuán)隊(duì)協(xié)作時(shí),所有人用同一套遷移文件,就能把本地/測(cè)試/生產(chǎn)數(shù)據(jù)庫結(jié)構(gòu)對(duì)齊。

6.1 為什么需要遷移

  • 可回顧:每次結(jié)構(gòu)變更都有對(duì)應(yīng) SQL 文件與命名(如 20240323120000_init)。
  • 可復(fù)現(xiàn):新同事或新環(huán)境執(zhí)行同一套遷移即可得到一致表結(jié)構(gòu)。
  • 與「只改庫不改文件」對(duì)比:手動(dòng)在 Navicat 里改表,無法自動(dòng)同步到其他人的機(jī)器,也容易與 schema.prisma 不一致。

6.2 開發(fā)環(huán)境常用命令:prisma migrate dev

首次或每次修改 schema.prisma 后:

npx prisma migrate dev --name 描述本次變更的英文短語

例如:

npx prisma migrate dev --name init
npx prisma migrate dev --name add_post_published_index

該命令會(huì):

  1. 對(duì)比當(dāng)前 schema 與數(shù)據(jù)庫狀態(tài),生成新的 SQL 遷移文件到 prisma/migrations/<時(shí)間戳>_<name>/migration.sql。
  2. 應(yīng)用這些遷移到當(dāng)前 DATABASE_URL 指向的數(shù)據(jù)庫。
  3. 觸發(fā) prisma generate,更新 Prisma Client。

適合:本地開發(fā)、共享開發(fā)數(shù)據(jù)庫(團(tuán)隊(duì)約定好同一條 DATABASE_URL 時(shí)要注意沖突)。

6.3 生產(chǎn) / CI:prisma migrate deploy

生產(chǎn)構(gòu)建流程或服務(wù)器上,不要migrate dev(它會(huì)交互式、且偏向開發(fā)工作流)。應(yīng)使用:

npx prisma migrate deploy

作用:只執(zhí)行 prisma/migrations尚未應(yīng)用的遷移,根據(jù)當(dāng)前數(shù)據(jù)庫反向改 schema,適合流水線與只讀權(quán)限受限的環(huán)境。

典型順序:

  1. 構(gòu)建應(yīng)用:npm run build
  2. 部署前或啟動(dòng)前:npx prisma migrate deploy
  3. 啟動(dòng):npm run start

6.4db push與migrate的區(qū)別

命令適用場(chǎng)景
prisma migrate dev有遷移歷史、團(tuán)隊(duì)需要版本化 SQL;推薦正式項(xiàng)目
prisma db push快速把 schema 推到數(shù)據(jù)庫,生成遷移文件;原型、個(gè)人玩具項(xiàng)目或明確不保留遷移歷史時(shí)可用

生產(chǎn)環(huán)境應(yīng)依賴 migrate deploy + 已提交的 migrations 文件夾,而不是 db push。

6.5prisma/migrations目錄里有什么

prisma/migrations/
├── migration_lock.toml       # 鎖定數(shù)據(jù)庫提供方(如 mysql)
└── 20240323120000_init/
    └── migration.sql         # 本次遷移的 SQL(由 Prisma 生成)
  • migration.sql:可閱讀、可審計(jì);一般不要手改(除非你很清楚后果)。
  • 新增遷移 = 新文件夾 + 新 SQL,按時(shí)間順序應(yīng)用。

6.6 常見注意點(diǎn)

  • 修改已部署過的遷移文件可能導(dǎo)致校驗(yàn)失?。灰焉暇€的變更應(yīng)通過新遷移追加修改。
  • 備份:生產(chǎn)執(zhí)行 migrate deploy 前應(yīng)有數(shù)據(jù)庫備份策略。
  • Serverless(如部分 Vercel 函數(shù))需注意 MySQL 連接數(shù);必要時(shí)使用連接池或官方推薦的托管方案。

七、Prisma Client 單例(避免開發(fā)環(huán)境連接耗盡)

lib/prisma.ts

import { PrismaClient } from "@prisma/client";

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

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;

八、在 Server Component 中查詢

app/users/page.tsx

import { prisma } from "@/lib/prisma";

export default async function UsersPage() {
  const users = await prisma.user.findMany({
    orderBy: { createdAt: "desc" },
    include: { posts: true },
  });

  return (
    <main>
      <h1>用戶列表</h1>
      <ul>
        {users.map((u) => (
          <li key={u.id}>
            {u.name ?? u.email} — 文章數(shù):{u.posts.length}
          </li>
        ))}
      </ul>
    </main>
  );
}

九、Route Handler 示例

app/api/users/route.ts

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";

export async function GET() {
  const users = await prisma.user.findMany();
  return NextResponse.json(users);
}

export async function POST(request: Request) {
  const body = await request.json();
  const { email, name } = body as { email: string; name?: string };

  const user = await prisma.user.create({
    data: { email, name },
  });

  return NextResponse.json(user, { status: 201 });
}

十、數(shù)據(jù)的修改與刪除接口(Route Handlers)

單條資源的 更新、刪除 通常不放在集合路徑 /api/users 上,而是使用 動(dòng)態(tài)路由 /api/users/[id]:路徑里的 id 對(duì)應(yīng)數(shù)據(jù)庫主鍵(或業(yè)務(wù)唯一標(biāo)識(shí)),與 REST 習(xí)慣一致(對(duì)「某一個(gè)用戶」做 PATCH/DELETE)。

10.1 路由文件位置

在 App Router 中新建:

app/api/users/[id]/route.ts

同一文件內(nèi)可導(dǎo)出 PATCH(部分更新)、PUT(全量更新,可選)、DELETE(刪除)。Next.js 按 HTTP 方法分發(fā)到對(duì)應(yīng)導(dǎo)出函數(shù)。

10.2PATCH:部分更新(常用)

客戶端只傳需要改的字段(例如只改 name),服務(wù)端用 prisma.user.update 合并進(jìn)數(shù)據(jù)庫。

要點(diǎn)

  • where:用 id 定位一行;若不存在,Prisma 拋出 P2025(Record not found),應(yīng)轉(zhuǎn)為 404。
  • data:只寫入請(qǐng)求體里出現(xiàn)的字段,避免把未傳字段覆蓋成 null(需自行從 body 解構(gòu)并組裝 data)。

app/api/users/[id]/route.ts 示例(Next.js 15+ 中 paramsPromise,需 await):

import { NextResponse } from "next/server";
import { Prisma } from "@prisma/client";
import { prisma } from "@/lib/prisma";

type Ctx = { params: Promise<{ id: string }> };

export async function PATCH(request: Request, ctx: Ctx) {
  const { id } = await ctx.params;
  const userId = Number(id);
  if (Number.isNaN(userId)) {
    return NextResponse.json({ error: "Invalid id" }, { status: 400 });
  }

  const body = await request.json();
  const { name, email } = body as { name?: string; email?: string };

  const data: { name?: string; email?: string } = {};
  if (name !== undefined) data.name = name;
  if (email !== undefined) data.email = email;
  if (Object.keys(data).length === 0) {
    return NextResponse.json({ error: "No fields to update" }, { status: 400 });
  }

  try {
    const user = await prisma.user.update({
      where: { id: userId },
      data,
    });
    return NextResponse.json(user);
  } catch (e) {
    if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }
    throw e;
  }
}

調(diào)用示例(前端或其他客戶端):

PATCH /api/users/1 HTTP/1.1
Content-Type: application/json

{"name": "新名字"}

10.3PUT:全量更新(可選)

語義上 PUT 常表示「用請(qǐng)求體替換整個(gè)資源」。若 User 只有 emailname 等少量字段,可以在服務(wù)端規(guī)定:必須帶上全部可寫字段,否則 400;再執(zhí)行 update

若業(yè)務(wù)上更關(guān)心「只改部分字段」,優(yōu)先用 PATCH,避免客戶端漏傳字段導(dǎo)致誤清空。

10.4DELETE:刪除一條記錄

使用 prisma.user.delete,成功時(shí)返回 204 No Content(無響應(yīng)體)較常見;也可返回 200 并帶上已刪除對(duì)象的 JSON,按團(tuán)隊(duì)約定即可。

import { NextResponse } from "next/server";
import { Prisma } from "@prisma/client";
import { prisma } from "@/lib/prisma";

type Ctx = { params: Promise<{ id: string }> };

export async function DELETE(_request: Request, ctx: Ctx) {
  const { id } = await ctx.params;
  const userId = Number(id);
  if (Number.isNaN(userId)) {
    return NextResponse.json({ error: "Invalid id" }, { status: 400 });
  }

  try {
    await prisma.user.delete({
      where: { id: userId },
    });
    return new NextResponse(null, { status: 204 });
  } catch (e) {
    if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }
    throw e;
  }
}

說明:若表上有 外鍵約束(例如 Post 依賴 User),刪除用戶可能觸發(fā) Prisma/MySQL 外鍵錯(cuò)誤(如 P2003),需在業(yè)務(wù)層先刪子表數(shù)據(jù)、或改用數(shù)據(jù)庫 ON DELETE CASCADE、或禁止刪除,并對(duì)該錯(cuò)誤返回 409 等狀態(tài)碼。

10.5 按條件批量更新 / 刪除(updateMany/deleteMany)

不通過 id 單條操作,而是按條件批量處理時(shí)使用:

// 將所有未發(fā)布文章標(biāo)為已發(fā)布(示例)
await prisma.post.updateMany({
  where: { published: false },
  data: { published: true },
});

// 刪除某郵箱前綴的測(cè)試用戶(慎用,生產(chǎn)需強(qiáng)校驗(yàn))
await prisma.user.deleteMany({
  where: { email: { startsWith: "test_" } },
});

要點(diǎn)updateMany / deleteMany 不會(huì)在 0 行匹配時(shí)拋錯(cuò);若接口需要「至少刪一行」再返回 404,需在執(zhí)行后根據(jù) count 自行判斷。

10.6 Next.js 14 與params類型說明

若項(xiàng)目仍為 Next.js 14,部分版本中 params同步對(duì)象,簽名可寫為 { params: { id: string } }不使用 await params。升級(jí)到 Next.js 15 后請(qǐng)改為 params: Promise<...>await params,與官方 Route Handlers 類型一致。

10.7 前端請(qǐng)求代碼(修改與刪除)

以下使用瀏覽器原生 fetch,適用于 客戶端組件(文件頂部需加 "use client")。請(qǐng)求路徑與上文 Route Handler 一致:/api/users/[id]。

要點(diǎn)

  • PATCH:設(shè)置 Content-Type: application/jsonbodyJSON.stringify 后的對(duì)象。
  • DELETE:若服務(wù)端返回 204 No Content,沒有響應(yīng)體,不要調(diào)用 response.json(),根據(jù) response.okresponse.status === 204 判斷成功。
  • 失敗時(shí)(4xx/5xx)若接口返回 JSON 錯(cuò)誤信息,可 await response.json() 讀?。ㄗ⒁庀扰袛?Content-Typetry/catch)。

封裝函數(shù)(可放在lib/user-api.ts或組件同文件內(nèi))

/** 部分更新用戶(對(duì)應(yīng) PATCH /api/users/:id) */
export async function updateUser(
  id: number,
  data: { name?: string; email?: string }
): Promise<{ id: number; name: string | null; email: string }> {
  const res = await fetch(`/api/users/${id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(data),
  });

  const payload = await res.json().catch(() => ({}));

  if (!res.ok) {
    const message =
      typeof payload === "object" && payload !== null && "error" in payload
        ? String((payload as { error: unknown }).error)
        : res.statusText;
    throw new Error(message || `HTTP ${res.status}`);
  }

  return payload as { id: number; name: string | null; email: string };
}

/** 刪除用戶(對(duì)應(yīng) DELETE /api/users/:id,成功為 204 無 body) */
export async function deleteUser(id: number): Promise<void> {
  const res = await fetch(`/api/users/${id}`, {
    method: "DELETE",
  });

  if (res.ok) {
    return;
  }

  let message = res.statusText;
  try {
    const payload = (await res.json()) as { error?: string };
    if (payload.error) message = payload.error;
  } catch {
    /* 無 JSON 時(shí)忽略 */
  }
  throw new Error(message || `HTTP ${res.status}`);
}

在客戶端組件中調(diào)用(示例)

"use client";

import { useState } from "react";
import { deleteUser, updateUser } from "@/lib/user-api";

export function UserActions({ userId }: { userId: number }) {
  const [loading, setLoading] = useState<"patch" | "delete" | null>(null);
  const [error, setError] = useState<string | null>(null);

  async function handleRename() {
    setError(null);
    setLoading("patch");
    try {
      const user = await updateUser(userId, { name: "新名字" });
      console.log("更新成功", user);
      // 例如:router.refresh() 或更新本地列表狀態(tài)
    } catch (e) {
      setError(e instanceof Error ? e.message : "更新失敗");
    } finally {
      setLoading(null);
    }
  }

  async function handleDelete() {
    if (!confirm("確定刪除該用戶?")) return;
    setError(null);
    setLoading("delete");
    try {
      await deleteUser(userId);
      console.log("刪除成功");
      // 例如:跳轉(zhuǎn)列表頁或從狀態(tài)中移除
    } catch (e) {
      setError(e instanceof Error ? e.message : "刪除失敗");
    } finally {
      setLoading(null);
    }
  }

  return (
    <div>
      {error && <p role="alert">{error}</p>}
      <button type="button" onClick={handleRename} disabled={loading !== null}>
        {loading === "patch" ? "更新中…" : "修改名字"}
      </button>
      <button type="button" onClick={handleDelete} disabled={loading !== null}>
        {loading === "delete" ? "刪除中…" : "刪除"}
      </button>
    </div>
  );
}

說明:若列表數(shù)據(jù)來自 Server Component,刪除/更新成功后可在子組件中調(diào)用 import { useRouter } from "next/navigation"router.refresh(),讓服務(wù)端重新渲染最新數(shù)據(jù);或使用全局狀態(tài) / React Query 等自行同步列表。

十一、事務(wù)示例

import { prisma } from "@/lib/prisma";

export async function createUserWithPost(email: string, postTitle: string) {
  return prisma.$transaction(async (tx) => {
    const user = await tx.user.create({
      data: { email },
    });
    await tx.post.create({
      data: {
        title: postTitle,
        authorId: user.id,
      },
    });
    return user;
  });
}

十二、小結(jié)

  • 從官網(wǎng)安裝 MySQL ServerMySQL Workbench,用 Workbench 測(cè)試連接建庫、執(zhí)行 SQL 與查看表數(shù)據(jù);下載頁MySQL Community Server、MySQL Installer(Windows)MySQL Workbench。
  • create-next-app 初始化項(xiàng)目,App Router 下頁面在 app/,API 在 app/api/.../route.ts
  • Prismaschema.prisma 定義模型;migrate dev 在開發(fā)中生成并應(yīng)用遷移;migrate deploy 在生產(chǎn)/CI 應(yīng)用已提交的遷移。
  • MySQL 通過 DATABASE_URL 連接;全棧鏈路為:Next(服務(wù)端)→ Prisma Client → MySQL。
  • 單條資源的修改與刪除使用 app/api/.../[id]/route.ts,導(dǎo)出 PATCH / DELETE(可選 PUT);不存在時(shí)處理 Prisma P2025 返回 404;批量操作用 updateMany / deleteMany。前端在客戶端組件中用 fetch 發(fā) PATCH(JSON body)與 DELETE204 無響應(yīng)體時(shí)不要 response.json()。
  • prisma 官網(wǎng):www.prisma.io/docs
  • next 官網(wǎng) nextjs.frontendx.cn/

到此這篇關(guān)于如何使用Next.js+Prisma+MySQL開發(fā)全棧項(xiàng)目的文章就介紹到這了,更多相關(guān)Next.js + Prisma + MySQL全棧項(xiàng)目?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React父組件如何調(diào)用子組件的方法推薦

    React父組件如何調(diào)用子組件的方法推薦

    在React中,我們經(jīng)常在子組件中調(diào)用父組件的方法,一般用props回調(diào)即可,這篇文章主要介紹了React父組件如何調(diào)用子組件的方法推薦,需要的朋友可以參考下
    2023-11-11
  • React router動(dòng)態(tài)加載組件之適配器模式的應(yīng)用詳解

    React router動(dòng)態(tài)加載組件之適配器模式的應(yīng)用詳解

    這篇文章主要介紹了React router動(dòng)態(tài)加載組件之適配器模式的應(yīng)用 ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • 詳解React?Native項(xiàng)目中啟用Hermes引擎

    詳解React?Native項(xiàng)目中啟用Hermes引擎

    這篇文章主要為大家介紹了React?Native項(xiàng)目中啟用Hermes引擎實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 使用 React 和 Threejs 創(chuàng)建一個(gè)VR全景項(xiàng)目的過程詳解

    使用 React 和 Threejs 創(chuàng)建一個(gè)VR全景項(xiàng)目的過程詳解

    這篇文章主要介紹了使用 React 和 Threejs 創(chuàng)建一個(gè)VR全景項(xiàng)目的過程詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • React?hooks中useState踩坑之異步的問題

    React?hooks中useState踩坑之異步的問題

    這篇文章主要介紹了React?hooks中useState踩坑之異步的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 學(xué)習(xí)ahooks useRequest并實(shí)現(xiàn)手寫

    學(xué)習(xí)ahooks useRequest并實(shí)現(xiàn)手寫

    這篇文章主要為大家介紹了學(xué)習(xí)ahooks useRequest并實(shí)現(xiàn)手寫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • React中常見的TypeScript定義實(shí)戰(zhàn)教程

    React中常見的TypeScript定義實(shí)戰(zhàn)教程

    這篇文章主要介紹了React中常見的TypeScript定義實(shí)戰(zhàn),本文介紹了Fiber結(jié)構(gòu),F(xiàn)iber的生成過程,調(diào)和過程,以及 render 和 commit 兩大階段,需要的朋友可以參考下
    2022-10-10
  • React中阻止事件冒泡的問題詳析

    React中阻止事件冒泡的問題詳析

    這篇文章主要給大家介紹了關(guān)于React中阻止事件冒泡問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用React具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 基于webpack4.X從零搭建React腳手架的方法步驟

    基于webpack4.X從零搭建React腳手架的方法步驟

    這篇文章主要介紹了基于webpack4.X從零搭建React腳手架的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • React框架核心原理全面深入解析

    React框架核心原理全面深入解析

    React是前端開發(fā)每天都用的前端框架,自然要深入掌握它的原理。我用 React 也挺久了,這篇文章就來總結(jié)一下我對(duì) react 原理的理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-11-11

最新評(píng)論

吴堡县| 叙永县| 五大连池市| 闸北区| 灵山县| 讷河市| 青神县| 阜新| 博湖县| 安徽省| 湖北省| 邓州市| 海林市| 江城| 景宁| 海丰县| 辽阳市| 元朗区| 皮山县| 莱西市| 松江区| 丹棱县| 通化市| 大悟县| 万源市| 襄城县| 马边| 双牌县| 呼图壁县| 梨树县| 大英县| 岱山县| 郓城县| 莱州市| 乳山市| 和政县| 鄯善县| 关岭| 台前县| 嘉祥县| 松江区|