数据库
本篇包括以下内容:
- 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,修改如下所示。
DATABASE_URL="mysql://USER:PASSWORD@HOST:PORT/DATABASE"
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
修改完成后建议把 .env
加入到 .gitignore
中,避免自己账号密码流出
定义 model
在 /prisma/schema.prisma
可以添加 model ,相当于数据库表,其格式如下,具体内容可以参考Prisma Model
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
<!-- 非关系型数据库 -->
npx prisma db push
使用该命令后,会在prisma/migrations/20240224061001_initial
中自动生成 .sql
文件,并会自动创建对应 Database。相应的,每次修改 /prisma/schema.prisma
中的 model 之后,运行该指令,都会生成对应的修改 sql 文件
创建 Prisma Client
在Prisma Creating Client这一节,给出了如何创建一个全局的 PrismaClient 供我们使用,其具体代码如下,我们只需要 CV 一次,后面直接使用即可。注意需要放到 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
方法来获取数据。
// 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 相关的筛选与排序语法
// 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 方法中
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 方法中
// 直接补全之前函数中空的部分
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 方法中
// 直接补全之前函数中空的部分
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({});
}