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

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

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

本文介紹如何用 Next.js、Prisma、MySQL 搭建全棧應(yīng)用:包含 MySQL 與 MySQL Workbench 的安裝與基本使用、創(chuà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 項目

2.1 前置條件

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

2.2 使用官方腳手架

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

npx create-next-app@latest my-app

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

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

進入項目并安裝依賴:

cd my-app
npm install

2.3 本地運行

npm run dev

瀏覽器訪問 http://localhost:3000。默認端口為 3000

2.4 常用腳本(package.json)

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

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

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

my-app/
├── app/                      # App Router:頁面、布局、路由
│   ├── layout.tsx            # 根布局(全局 HTML 殼、字體、Provider)
│   ├── page.tsx              # 路由 "/" 的首頁
│   ├── globals.css           # 全局樣式
│   ├── loading.tsx           # 可選:該路由段的加載 UI(Suspense)
│   ├── error.tsx             # 可選:該路由段的錯誤邊界
│   └── api/                  # Route Handlers(HTTP API)
│       └── users/
│           └── route.ts      # 對應(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/               # 可復用 UI 組件(自建)
├── .env                      # 本地環(huán)境變量(勿提交密鑰)
├── .env.example              # 環(huán)境變量示例(可提交)
├── next.config.ts / .js      # Next 構(gòu)建與運行時配置
├── tsconfig.json             # TypeScript 配置
└── package.json

3.1app/目錄

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

3.2public/

放不需要經(jīng)過打包處理的靜態(tài)文件,例如 public/logo.png 對應(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.*:圖片域名、重定向、實驗特性等。
  • tsconfig.json:路徑別名(如 @/*)常在這里配置,與 import 有關(guān)。

四、MySQL 安裝與 MySQL Workbench

4.1 官方下載地址

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

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

說明

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

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

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

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

4.3 安裝后如何確認 MySQL 已運行

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

4.4 安裝 MySQL Workbench

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

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

  1. 打開 MySQL Workbench
  2. 主界面 MySQL Connections 區(qū)域點擊 「+」MySQL Connections 旁的加號,新建連接。
  3. 填寫連接參數(shù)(本地開發(fā)常見值):
字段典型值說明
Connection Name任意名稱,如 Local Dev僅顯示用
Hostname127.0.0.1localhost本機數(shù)據(jù)庫
Port3306與安裝時一致
Usernameroot或你創(chuàng)建的其他用戶
Password點擊 Store in Keychain / Vault… 保存密碼,避免每次輸入
  1. 點擊 Test Connection,提示成功即可 OK 保存。
  2. 雙擊該連接進入主工作區(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 或工具欄新建查詢標簽 → 輸入 SQL → 選中語句 → 點擊 閃電圖標 執(zhí)行(或 Ctrl + Enter)。
查看表數(shù)據(jù)Schemas 中展開數(shù)據(jù)庫 → Tables → 表名右鍵 → Select Rows - Limit 1000。
查看表結(jié)構(gòu)表名右鍵 → Table InspectorAlter Table。
新建用戶/授權(quán)(進階)菜單 Server → Users and Privileges(需相應(yīng)權(quán)限);開發(fā)階段常用 root,生產(chǎn)環(huán)境應(yīng)使用最小權(quán)限賬號。

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

五、接入 Prisma 與 MySQL

5.1 安裝

npm install prisma @prisma/client
npx prisma init

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

5.2 配置連接串(.env)

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

示例(本地 MySQL):

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

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

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

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

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

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

6.1 為什么需要遷移

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

該命令會:

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

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

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

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

npx prisma migrate deploy

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

典型順序:

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

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

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

生產(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:可閱讀、可審計;一般不要手改(除非你很清楚后果)。
  • 新增遷移 = 新文件夾 + 新 SQL,按時間順序應(yīng)用。

6.6 常見注意點

  • 修改已部署過的遷移文件可能導致校驗失??;已上線的變更應(yīng)通過新遷移追加修改。
  • 備份:生產(chǎn)執(zhí)行 migrate deploy 前應(yīng)有數(shù)據(jù)庫備份策略。
  • Serverless(如部分 Vercel 函數(shù))需注意 MySQL 連接數(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 上,而是使用 動態(tài)路由 /api/users/[id]:路徑里的 id 對應(yīng)數(shù)據(jù)庫主鍵(或業(yè)務(wù)唯一標識),與 REST 習慣一致(對「某一個用戶」做 PATCH/DELETE)。

10.1 路由文件位置

在 App Router 中新建:

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

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

10.2PATCH:部分更新(常用)

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

要點

  • where:用 id 定位一行;若不存在,Prisma 拋出 P2025(Record not found),應(yīng)轉(zhuǎn)為 404
  • data:只寫入請求體里出現(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 常表示「用請求體替換整個資源」。若 User 只有 emailname 等少量字段,可以在服務(wù)端規(guī)定:必須帶上全部可寫字段,否則 400;再執(zhí)行 update

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

10.4DELETE:刪除一條記錄

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

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 外鍵錯誤(如 P2003),需在業(yè)務(wù)層先刪子表數(shù)據(jù)、或改用數(shù)據(jù)庫 ON DELETE CASCADE、或禁止刪除,并對該錯誤返回 409 等狀態(tài)碼。

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

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

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

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

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

10.6 Next.js 14 與params類型說明

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

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

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

要點

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

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

/** 部分更新用戶(對應(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 };
}

/** 刪除用戶(對應(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 時忽略 */
  }
  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 測試連接、建庫執(zhí)行 SQL 與查看表數(shù)據(jù);下載頁MySQL Community ServerMySQL Installer(Windows)、MySQL Workbench
  • create-next-app 初始化項目,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,導出 PATCH / DELETE(可選 PUT);不存在時處理 Prisma P2025 返回 404;批量操作用 updateMany / deleteMany。前端在客戶端組件中用 fetch 發(fā) PATCH(JSON body)與 DELETE,204 無響應(yīng)體時不要 response.json()。
  • prisma 官網(wǎng):www.prisma.io/docs
  • next 官網(wǎng) nextjs.frontendx.cn/

到此這篇關(guān)于如何使用Next.js+Prisma+MySQL開發(fā)全棧項目的文章就介紹到這了,更多相關(guān)Next.js + Prisma + MySQL全棧項目內(nèi)容請搜索腳本之家以前的文章或繼續(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動態(tài)加載組件之適配器模式的應(yīng)用詳解

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

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

    詳解React?Native項目中啟用Hermes引擎

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

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

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

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

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

    學習ahooks useRequest并實現(xiàn)手寫

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

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

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

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

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

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

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

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

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

最新評論

喀喇| 安溪县| 台安县| 溧水县| 罗甸县| 修武县| 志丹县| 会昌县| 滕州市| 疏勒县| 墨江| 东城区| 阿拉善右旗| 曲阳县| 四平市| 和平区| 五台县| 中西区| 江阴市| 吐鲁番市| 万荣县| 镇沅| 沽源县| 临泽县| 新乡市| 扎鲁特旗| 措美县| 明水县| 定西市| 桑植县| 云林县| 盱眙县| 个旧市| 黎川县| 绥阳县| 多伦县| 潜江市| 普定县| 汉中市| 甘泉县| 盐源县|