Skip to main content

数据库

本篇包括以下内容:

  • Setting up Prisma
  • Defining data models
  • Creating migrations
  • Performing CRUD operations

Prisma

本章代码链接

Prisma 是一款 ORM(Object–relational mapping) 软件。使用 npm i prisma 命令安装 Prisma

安装好后,使用 npx prisma init 初始化 Prisma。init 好之后,会有 /prisma/schema.prisma.env 两个文件

可以根据自己使用的数据库来修改一下,在Prisma Connection String查看设置文档。笔者使用的是 MySQL,修改如下所示。

.env
DATABASE_URL="mysql://USER:PASSWORD@HOST:PORT/DATABASE"
/prisma/schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}

修改完成后建议把 .env 加入到 .gitignore 中,避免自己账号密码流出

定义 model

本章代码链接

/prisma/schema.prisma 可以添加 model ,相当于数据库表,其格式如下,具体内容可以参考Prisma Model

/prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String
followers Int @default(0)
isActive Boolean @default(true)
}

在写好之后可以使用 npx prisma format 来格式化,会自动进行对齐等操作

同步到数据库

本章代码链接

在创建好 model 之后,可以通过下面的命令来同步到数据库

<!-- 关系型数据库 -->
npx prisma migrate dev

使用该命令后,会在prisma/migrations/20240224061001_initial 中自动生成 .sql 文件,并会自动创建对应 Database。相应的,每次修改 /prisma/schema.prisma 中的 model 之后,运行该指令,都会生成对应的修改 sql 文件

创建 Prisma Client

本章代码链接

Prisma Creating Client这一节,给出了如何创建一个全局的 PrismaClient 供我们使用,其具体代码如下,我们只需要 CV 一次,后面直接使用即可。注意需要放到 prisma/client.ts

Prisma Client

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

const prismaClientSingleton = () => {
return new PrismaClient();
};

declare global {
var prisma: undefined | ReturnType<typeof prismaClientSingleton>;
}

const prisma = globalThis.prisma ?? prismaClientSingleton();

export default prisma;

if (process.env.NODE_ENV !== "production") globalThis.prisma = prisma;

获取数据

本章代码链接

需要获取数据时,导入全局的 prismaClient 对象,用 .findUnique.findMany 方法来获取数据。

api/users/route.tsx
  // findMany 方法
import schema from "./schema";
// 导入 prisma
+ import prisma from "@/prisma/client";

- export function GET(request: NextRequest) {
- return NextResponse.json([
- { id: 1, name: "Castamere" },
- { id: 2, name: "Today_Red" },
- ]);

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

同样我们可以将之前动态路由中的参数([id])作为筛选项来获取数据,只需要调用 findUnique 方法即可(在 GET 方法中)。在Prisma Filtering and Sorting可以找到 prisma 相关的筛选与排序语法

api/users/[id]/route.tsx
  // findUnique 方法
import { NextRequest, NextResponse } from "next/server";
import schema from "../schema";
// 导入 prisma
+ import prisma from "@/prisma/client";

export async function GET(
request: NextRequest,
// 这里提到前文一个错误,slug中的id,比如 user/1,这个1被读取时是String而非number,使用时需要手动 parseInt
- { params: { id } }: { params: { id: number } }
+ { params: { id } }: { params: { id: string } }
) {
+ const user = await prisma.user.findUnique({ where: { id: parseInt(id) } });
if (!user)
return NextResponse.json({ error: "User not found" }, { status: 404 });
return NextResponse.json({ user });
}

上传数据

本章代码链接

上传数据直接调用 prisma.user.create() 方法即可,用在 POST 方法中

api/users/route.tsx
export async function POST(request: NextRequest) {
const body = await request.json();
const validation = schema.safeParse(body);
if (!validation.success)
return NextResponse.json(validation.error.errors, { status: 400 });
// 检查是否已有重复
const check = await prisma.user.findUnique({
where: { email: body.email },
});
if (check)
return NextResponse.json({ error: "User already exists" }, { status: 400 });
// 上传数据
const user = await prisma.user.create({
data: {
name: body.name,
email: body.email,
},
});
return NextResponse.json(user, { status: 201 });
}

修改数据

本章代码链接

修改数据则调用 prisma.user.update(),注意用在 PUT 方法中

api/users/[id]/route.tsx
  // 直接补全之前函数中空的部分
export async function PUT(
request: NextRequest,
{ params: { id } }: { params: { id: string } }
) {
// Validate the request body
const body = await request.json();
const validation = schema.safeParse(body);
// If invalid, return 400
if (!validation.success)
return NextResponse.json(validation.error.errors, { status: 400 });
// Fetch the user
+ const user = await prisma.user.findUnique({
+ where: { id: parseInt(id) },
+ });
// If does not exist, return 404
if (!user)
return NextResponse.json({ error: "User not found" }, { status: 404 });
// Update the user
+ const updatedUser = await prisma.user.update({
+ where: { id: user.id },
+ data: {
+ name: body.name,
+ email: body.email,
+ },
+ });
// Return the updated user
return NextResponse.json(updatedUser);
}

删除数据

本章代码链接

删除数据调用 prisma.user.delete(),注意用在 DELETE 方法中

api/users/[id]/route.tsx
  // 直接补全之前函数中空的部分
export async function DELETE(
request: NextRequest,
{ params: { id } }: { params: { id: string } }
) {
// Fetch user from db
+ const user = await prisma.user.findUnique({
+ where: { id: parseInt(id) },
+ });
// If does not exist, return 404
if (!user)
return NextResponse.json({ error: "User not found" }, { status: 404 });
// Delete the user
+ await prisma.user.delete({
+ where: { id: user.id },
+ });
// Return 200
return NextResponse.json({});
}
Buy me a coffee ☕: