Prisma 是一个现代化的数据库工具链,它提供了一个类型安全的 ORM(对象关系映射),使得开发者能够轻松地与数据库进行交互。通过 Prisma,可以自动生成类型化的数据库查询,减少了手写 SQL 的需求,是构建高效、可扩展的数据库应用的理想选择。
1. Vercel Postgres 免费数据库
Vercel 平台推出了数据库存储服务,对于免费用户,每月的数据库操作 10 万次,存储 10 G,写个小小的个人站点足够了。
Vercel 平台上 Storage tab下新建一个 Prisma Postgres 数据服务,在.env文件粘贴Vercel的数据库地址DATABASE_URL="************",本地的数据库操作都会直接影响远程存储。
2. Prisma 项目初始化
Prisma 是一个基于 Nodejs 和 TypeScript 的 ORM,它可以帮助开发者以 更快的开发速度 和 更少的错误 来 管理数据库。
具体步骤参考官方指南How to use Prisma ORM with Next.js,我生成的客户端目录与官网不同,其他内容都一致
- 安装及初始化配置
安装依赖
npm install prisma tsx --save-dev
npm install @prisma/extension-accelerate @prisma/client
初始化配置
npx prisma init --db --output ../src/generated/prisma
这步操作会做下列事项:
- 一个包含 schema.prisma 文件的 prisma 目录。
- 一个 Prisma Postgres 数据库。
- 项目根目录下包含 DATABASE_URL 的 .env 文件。
- 定义生成的 Prisma Client 输出目录为 src/generated/prisma。
- 定义模型配置
修改我们需要的博客模型,id 使用cuid()生成,会比纯数字自增更合适,起码不容易被恶意爬虫抓数据
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
output = "../src/generated/prisma"
}
generator pothos {
provider = "prisma-pothos-types"
}
model User {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
image String?
nickname String @default("")
role Role @default(USER)
bookmarks Link[]
posts Post[]
}
enum Role {
USER
ADMIN
}
model Post {
id String @id @default(cuid())
title String
summary String @default("")
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdBy User @relation(fields: [createdById], references: [id])
createdById String
}
- 配置Prisma客户端
npx prisma migrate dev --name init
这一步操作会在本地建立 User 表 和 Post 表,生成 prisma 客户端文件
后期模型有修改都需要执行 npx prisma migrate dev --name xxxx,同步修改表信息
查看本地数据库页面 npx prisma studio,保存修改会同步到远程存储
3. 使用Prisma操作数据库
- 设置prisma客户端
前一步生成的客户端文件,在这里直接导进来
//src/lib/prisma.ts
import { PrismaClient } from '../generated/prisma'
import { withAccelerate } from '@prisma/extension-accelerate'
const globalForPrisma = global as unknown as {
prisma: PrismaClient
}
const prisma =
globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate())
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
- 查文章列表
import prisma from '@/lib/prisma'
const posts = await prisma.post.findMany()
- 新建文章
import prisma from '@/lib/prisma'
await prisma.post.create({
data: {
title,
content,
},
})
- 更新文章
import prisma from '@/lib/prisma'
const post = await prisma.post.update({
where: { id },
data: { title, summary, content },
})
- 删除文章
import prisma from '@/lib/prisma'
await prisma.post.delete({
where: { id },
})