【NextJS】PostgreSQL 遇上 Prisma ORM
NextJS 数据库 之 遇上Prisma ORM
前言
在
Next.js
全栈开发的时候不免要用到数据库,采用原生数据库语法可能还需要顾虑很多方面的问题(语法安全、原生语法麻烦/繁琐/复杂、更换数据库时的语法兼容等等),为了解决这类问题诞生了ORM(Object-Relational Mapping)
数据访问方式技术及周边工具;
这里介绍一个易用又强大的ORM
框架/工具库:Prisma ORM
官网:https://www.prisma.io/
GitHub:https://github.com/prisma/prisma
内容包含以下两个部分:
-
重点概念
Prisma Schema Language (PSL).
:用来描述数据库架构的语言
-
两个主要(常用)操作库
Prisma Client
:为 Node.js 和 TypeScript 自动生成类型安全的查询生成器
可用于任何Node.js
或TypeScript
后端应用程序(包括无服务器应用程序和微服务)。Prisma Migrate
:声明式数据建模和迁移系统
主要用于生产部署、数据迁移等应用场景
-
附
Prisma CLI
:辅助快捷的操作命令工具
延展辅助(平台服务):
Prisma Postgres
[链接]:托管的 PostgreSQL 数据库服务Prisma Accelerate
[链接]:针对现有数据库的完全托管的全局连接池和缓存层,可直接从 Prisma ORM 支持查询级缓存策略。Prisma Optimize
[链接]:针对数据操作,基于AI进行优化分析服务Prisma Studio
[链接]:用于查看和编辑等操作的数据库可视化GUI工具
一、环境要求
最新环境要求可前往官方文档:https://www.prisma.io/docs/orm/reference/system-requirements
软件:
工具 | 最低要求版本 |
---|---|
Node.js | 18.8 / 20.9 / 22.11 |
TypeScript (可选) | 5.1.X |
Yarn (可选) | 1.19.2(当使用Yarn 1时) |
操作系统:
Linux:
- OpenSSL 1.0.x、1.1.x 或 3.x
- zlib(libz.so.1)
- libgcc( libgcc_s.so.1)
- C 标准库(大多数 Linux 发行版上的 glibc 或 Alpine Linux 上的 musl libc)
Windows:
- Microsoft Visual C++ 可再发行组件 2015或必须安装更新版本
macOS:
- macOS 10.15 或更新版本
二、概念介绍
1、Prisma Schema Language(PSL) 结构描述语言
1.1 概念
Prisma Schema Language
(简称:PSL
) - Prisma ORM 的核心部分
用于定义数据库模型
、关系
、以及生成 Prisma Client 的配置文件
。
- 【Prisma Schema 参数文档】:https://www.prisma.io/docs/orm/reference/prisma-schema-reference
想要将架构拆分为多个文件? Prisma ORM 5.15.0 及更高版本中的 prismaSchemaFolder 预览功能 支持多文件 Prisma Schema 。
它是一个声明式语言
,通过定义 .prisma
文件来描述数据库结构
和关系
。
Prisma Client
将基于(PSL
)生成数据库交互代码。
1.2 组成
Data Source
:数据库源(例如:PostgreSQL
orMongoDB
…)Generators
:数据模型生成器(例如:Prisma Client)Data model definition
:数据模型定义(例如,user数据表有哪些字段、分别什么数据类型等)
1.2.1 Data Source 数据源
定义数据库的连接信息,通常包括数据库的类型(例如PostgreSQL、MySQL、SQLite等)、连接URL、以及数据库的其他配置。
示例:
datasource db {
provider = "postgresql" // 指定 PostgreSQL 作为数据库
url = env("DATABASE_URL") // 从环境变量 DATABASE_URL 获取连接字符串
}
1.2.2 Generators 生成器
定义生成器的配置,Prisma默认使用生成Prisma Client。
通常会在此配置生成的Prisma Client存放的位置,以及语言(TypeScript/JavaScript)。
示例:
generator client {
provider = "prisma-client-js"
output = "./generated/client"
}
1.2.3 Data Model Definition 数据模型定义
定义数据库中的
实体(表)
。每个model
对应数据库中的一个表,表的字段对应model
中的属性
。
可以定义字段的类型
、默认值
、约束
(如@id
、@unique
等)以及关系
(如@relation
)。
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
author User @relation(fields: [authorId], references: [id])
authorId Int
}
字段(数据)类型和约束
每个字段可以指定数据类型,支持多种类型,如Int
、String
、Boolean
、DateTime
、Float
、Decimal
等。
可以通过@default()
设置默认值,@unique
设置唯一约束,@id
定义主键等。
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(false)
createdAt DateTime @default(now())
}
关系(Relations)
PSL
支持定义实体之间的关系。常见的关系包括一对一(1:1)
、一对多(1:N)
和多对多(M:N)
。通过@relation
定义。
// 示例:一对多关系
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
userId Int
author User @relation(fields: [userId], references: [id])
}
枚举(Enum)
PSL
还支持枚举类型,用于表示有多个固定选项的字段。
// 示例
enum Role {
USER
ADMIN
MODERATOR
}
model User {
id Int @id @default(autoincrement())
name String
role Role
}
更多数据模型内容可以前往官方文档探索:https://www.prisma.io/docs/orm/prisma-schema/data-model
2、Prisma Client 数据交互接口
2.1 概念
Prisma Client
是Prisma ORM
的主要组成部分,它是一个自动生成的数据库查询客户端,用于与数据库进行交互。
提供一种类型安全的方式来执行数据库操作,简化与数据库的连接和操作。
- 【Prisma Client API文档】:https://www.prisma.io/docs/orm/reference/prisma-client-reference
关键特点:
- 自动生成:根据数据库模式(
schema.prisma
文件)自动生成一个类型安全的客户端库(代码) - 类型安全:使用
TypeScript
来生成类型定义,这意味着在开发过程中,可以获得类型推导和自动补全,数据操作无需手动编写原始SQL语法交由Prisma Client
提供的API
使用JavaScript/TypeScript
中的类型安全语法 - 完善接口(API):包含CRUD、关联、分页和排序、事务操作等
- 数据库支持:
PostgreSQL
、MySQL
、MariaDB
、SQL Server
、SQLite
、CockroachDB
、MongoDB
各类主流数据库
2.2 使用示例
- 定义数据库模型(
schema.prisma
)
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
}
- 模型构建
pnpx prisma generate
- 在代码中使用
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const users = await prisma.user.findMany();
console.log(users);
}
main().catch(e => {
throw e
}).finally(async () => {
await prisma.$disconnect()
});
3、Prisma Migrate 迁移与种子
3.1 概念
Prisma Migrate
是Prisma ORM
中用于数据库迁移的工具。
通过自动生成和执行 SQL 迁移脚本来管理数据库结构变化,同时确保数据库结构与Prisma Schema
文件(schema.prisma
)保持一致。
3.2 迁移流程
通常的工作流程包括以下几个步骤:
- 修改 Prisma 模式:你在
schema.prisma
文件中修改数据库模型。 - 创建迁移文件:运行
prisma migrate dev
或prisma migrate create
命令,自动生成迁移文件。 - 应用迁移:通过
prisma migrate deploy
或prisma migrate dev
将迁移应用到数据库。 - 查看迁移历史:Prisma 会在数据库中跟踪迁移历史,确保每次迁移都按顺序应用。
3.3 数据库迁移(Migrate)
3.3 数据种子(Seeding)
4、Prisma CLI 命令行工具
init
参数 | 默认 | 描述 |
---|---|---|
--datasource-provider | postgresql | 指定块provider中字段的值datasource。选项包括sqlite、postgresql、mysql、和。sqlservermongodbcockroachdb |
--url | 定义自定义数据源 URL | |
--with-model | 在初始 Prisma 模式中添加一个简单的用户模型。自 5.14.0 版起可用 。 | |
--output | node_modules/.prisma/client | 指定生成的客户端的输出位置 |
--generator-provider | prisma-client-js | 定义要使用的生成器提供程序 |
--preview-feature | 定义要使用的预览功能 |
示例:
pnpx prisma init --datasource-provider PostgreSQL
generate
参数 | 默认 | 描述 |
---|---|---|
--no-engine | 生成不带附带引擎的 Prisma Client 以与Prisma Accelerate–data-proxy一起使用。与和互斥–accelerate。在 Prisma ORM 5.2.0 及更高版本中可用。 | |
--no-hints | 生成 Prisma Client,但不会在终端上打印使用提示。在 Prisma ORM 5.16.0 及更高版本中可用。 | |
--allow-no-models | 将生成 Prisma Client,但不生成任何模型 | |
--watch | 监视schema.prisma文件并在文件更改时重新生成 Prisma Client |
示例:
prisma generate
其他的后续再整理补充…
三、Next.js 中应用示例
以
Next.js
+PostgreSQL
组合为例!
node环境:
- node:v20.17.0
- pnpm:9.15.3
1、全新项目示例
1.1 项目初始化
- react:^19.0.0
- next:15.1.4
- pg:^8.13.1
- @prisma/client:^6.2.1
pnpx create-next-app@latest
// 安装时,将看到以下提示:
✔ What is your project named? … .
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like your code inside a `src/` directory? … No
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to use Turbopack for `next dev`? … No
✔ Would you like to customize the import alias (`@/*` by default)? … No
增加依赖包:pg
、@prisma/client
pnpm add pg @prisma/client
1.2 初始化Prisma ORM
// 初始化兼容PostgreSQL驱动数据库
pnpx prisma init --datasource-provider PostgreSQL
// 将看到以下提示:
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.
Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Run prisma db pull to turn your database schema into a Prisma schema.
3. Run prisma generate to generate the Prisma Client. You can then start querying your database.
4. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and real-time database events. Read: https://pris.ly/cli/beyond-orm
More information in our documentation:
https://pris.ly/d/getting-started
至此,基础环境搞定,接下来重点查看编辑两个文件:.env
和prisma/schema.prisma
在.env
文件中,重点设置DATABASE_URL
的值,用于建立数据库连接的配置
DATABASE_URL="postgresql://[username]:[password]@[ip|domain]:[port|5432]/[database][?param1=value1¶m2=value2&...]"
在prisma/schema.prisma
文件中,对生成器、数据模型进行配置
generator client {
provider = "prisma-client-js"
output = "./client" // 配置生成器的代码生成位置(相对schema.prisma文件所在目录)
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// 以下部分均为数据模型构建配置
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean
user User @relation(fields: [userId], references: [id])
userId Int
}
完成以上配置后,开始生成Prisma客户端代码:
// 生成Prisma客户端
pnpx prisma generate
// 将看到以下提示:
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
✔ Generated Prisma Client (v6.2.1) to ./prisma/client in 24ms
Start by importing your Prisma Client (See: https://pris.ly/d/importing-client)
Tip: Need your database queries to be 1000x faster? Accelerate offers you that and more: https://pris.ly/tip-2-accelerate
1.3 数据迁移
将数据模型推送到数据库中
// 模型推送
pnpx prisma db push
// 将看到以下提示:
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "xxxx", schema "public" at "xxxx:5432"
🚀 Your database is now in sync with your Prisma schema. Done in 6.22s
✔ Generated Prisma Client (v6.2.1) to ./prisma/client in 28ms
1.4 播种数据(可选)
添加
ts-node
和@types/node
到开发依赖项pnpm add -D ts-node @types/node
Ps:非
TypeScript
项目需要增加typescript
依赖包
在prisma
目录下创建一个seed.ts
文件,写入播种数据
// 导入 PrismaClient(注:pnpx prisma generate生成的代码)
import { PrismaClient } from './client'
// 创建 PrismaClient 实例
const prisma = new PrismaClient()
// 定义 main 函数
async function main() {
// 使用 upsert 方法创建或更新用户
const alice = await prisma.user.upsert({
where: { email: 'alice@prisma.io' },
update: {},
create: {
email: 'alice@prisma.io',
name: 'Alice',
posts: {
create: {
title: 'Check out Prisma with Next.js',
content: 'https://www.prisma.io/nextjs',
published: true,
},
},
},
})
// 创建另一个用户
const bob = await prisma.user.upsert({
where: { email: 'bob@prisma.io' },
update: {},
create: {
email: 'bob@prisma.io',
name: 'Bob',
posts: {
create: [
{
title: 'Follow Prisma on Twitter',
content: 'https://twitter.com/prisma',
published: true,
},
{
title: 'Follow Nexus on Twitter',
content: 'https://twitter.com/nexusgql',
published: true,
},
],
},
},
})
console.log({ alice, bob })
}
// 执行 main 函数并处理错误
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
在package.json
文件中新增以下配置,告诉prisma播种文件所在位置及其他配置信息
{
// .....
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
// .....
}
将种子数据推送上数据库里
// 种子推送
pnpx prisma db seed
// 将看到以下提示:
Environment variables loaded from .env
Running seed command `ts-node --compiler-options {"module":"CommonJS"} prisma/seed.ts` ...
{
alice: { id: 1, email: 'alice@prisma.io', name: 'Alice' },
bob: { id: 2, email: 'bob@prisma.io', name: 'Bob' }
}
🌱 The seed command has been executed.
1.5 模拟业务
创建一个api接口
GET /api/users
用于获取用户表所有数据
1、实例化 Prisma 客户端
在prisma
目录创建一个db.ts
文件,用于实例化
// file:/prisma/db.ts
import {PrismaClient} from './client'
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }
export const prisma = globalForPrisma.prisma || new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
2、创建数据API接口
"use server";
import {NextResponse} from 'next/server'
// 导入客户端实例
import prisma from "@/prisma/db"
export async function GET() {
// 使用findMany方法获取user表相关数据
const allUsers = await prisma.user.findMany();
return NextResponse.json({
message: 'Hello World',
data: allUsers
}, {status: 200});
}
3、测试获取是否正常
有何不足之处欢迎评论区或者私信我
原文地址:https://blog.csdn.net/u011159821/article/details/145182483
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!