【NextJS】PostgreSQL 遇上 Prisma ORM

NextJS 数据库 之 遇上Prisma ORM

  • 前言
  • 一、环境要求
  • 二、概念介绍
    • 1、Prisma Schema Language(PSL) 结构描述语言
      • 1.1 概念
      • 1.2 组成
        • 1.2.1 Data Source 数据源
        • 1.2.2 Generators 生成器
        • 1.2.3 Data Model Definition 数据模型定义
          • 字段(数据)类型和约束
          • 关系(Relations)
          • 枚举(Enum)
    • 2、Prisma Client 数据交互接口
      • 2.1 概念
      • 2.2 使用示例
    • 3、Prisma Migrate 迁移与种子
      • 3.1 概念
      • 3.2 迁移流程
      • 3.3 数据库迁移(Migrate)
      • 3.3 数据种子(Seeding)
    • 4、Prisma CLI 命令行工具
      • init
      • generate
  • 三、Next.js 中应用示例
    • 1、全新项目示例
      • 1.1 项目初始化
      • 1.2 初始化Prisma ORM
      • 1.3 数据迁移
      • 1.4 播种数据(可选)
      • 1.5 模拟业务

前言

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.jsTypeScript 后端应用程序(包括无服务器应用程序和微服务)。
    • 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.js18.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 or MongoDB…)
  • 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 @uniquename  Stringposts Post[]
}model Post {id      Int    @id @default(autoincrement())title   Stringcontent String?author  User   @relation(fields: [authorId], references: [id])authorId Int
}
字段(数据)类型和约束

每个字段可以指定数据类型,支持多种类型,如IntStringBooleanDateTimeFloatDecimal等。
可以通过@default()设置默认值,@unique设置唯一约束,@id定义主键等。

  • 更多内置约束:https://www.prisma.io/docs/orm/reference/prisma-schema-reference#attributes
model Post {id        Int      @id @default(autoincrement())title     Stringpublished Boolean  @default(false)createdAt DateTime @default(now())
}
关系(Relations)

PSL支持定义实体之间的关系。常见的关系包括一对一(1:1)一对多(1:N)多对多(M:N)。通过@relation定义。

  • 更多关系说明:https://www.prisma.io/docs/orm/prisma-schema/data-model/relations
// 示例:一对多关系model User {id    Int    @id @default(autoincrement())posts Post[]
}model Post {id      Int    @id @default(autoincrement())userId  Intauthor  User   @relation(fields: [userId], references: [id])
}
枚举(Enum)

PSL还支持枚举类型,用于表示有多个固定选项的字段。

// 示例enum Role {USERADMINMODERATOR
}model User {id    Int    @id @default(autoincrement())name  Stringrole  Role
}

更多数据模型内容可以前往官方文档探索:https://www.prisma.io/docs/orm/prisma-schema/data-model

2、Prisma Client 数据交互接口

2.1 概念

Prisma ClientPrisma 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、关联、分页和排序、事务操作等
  • 数据库支持PostgreSQLMySQLMariaDBSQL ServerSQLiteCockroachDBMongoDB 各类主流数据库

2.2 使用示例

  1. 定义数据库模型(schema.prisma
datasource db {provider = "postgresql"url      = env("DATABASE_URL")
}generator client {provider = "prisma-client-js"
}model User {id    Int    @id @default(autoincrement())name  Stringemail String @unique
}
  1. 模型构建
pnpx prisma generate
  1. 在代码中使用
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 MigratePrisma ORM 中用于数据库迁移的工具。
通过自动生成和执行 SQL 迁移脚本来管理数据库结构变化,同时确保数据库结构与 Prisma Schema 文件(schema.prisma)保持一致。

3.2 迁移流程

Prisma ORM 的集成数据库迁移工具-工作流程
通常的工作流程包括以下几个步骤:

  • 修改 Prisma 模式:你在 schema.prisma 文件中修改数据库模型。
  • 创建迁移文件:运行 prisma migrate devprisma migrate create 命令,自动生成迁移文件。
  • 应用迁移:通过 prisma migrate deployprisma migrate dev 将迁移应用到数据库。
  • 查看迁移历史:Prisma 会在数据库中跟踪迁移历史,确保每次迁移都按顺序应用。

3.3 数据库迁移(Migrate)

3.3 数据种子(Seeding)

4、Prisma CLI 命令行工具

  • 文档[英]
  • 支持指令[英]

init

参数默认描述
--datasource-providerpostgresql指定块provider中字段的值datasource。选项包括sqlite、postgresql、mysql、和。sqlservermongodbcockroachdb
--url定义自定义数据源 URL
--with-model在初始 Prisma 模式中添加一个简单的用户模型。自 5.14.0 版起可用
--outputnode_modules/.prisma/client指定生成的客户端的输出位置
--generator-providerprisma-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.prismaYou 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-ormMore information in our documentation:
https://pris.ly/d/getting-started

至此,基础环境搞定,接下来重点查看编辑两个文件:.envprisma/schema.prisma
在这里插入图片描述
.env文件中,重点设置DATABASE_URL的值,用于建立数据库连接的配置

DATABASE_URL="postgresql://[username]:[password]@[ip|domain]:[port|5432]/[database][?param1=value1&param2=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 @uniquename  Stringposts Post[]
}model Post {id        Int     @id @default(autoincrement())title     Stringcontent   Stringpublished Booleanuser      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 24msStart 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.tsimport {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 = prismaexport 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、测试获取是否正常
在这里插入图片描述


有何不足之处欢迎评论区或者私信我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/67454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

左神算法基础提升--3

文章目录 Manacher 算法经典算法Manacher算法原理 单调栈或单调队列 Manacher 算法 经典算法 在每学习Manacher算法之前我们可能会使用一种比较经典暴力的算法:遍历str字符串,将字符串中的每个字符作为对称点,向两边扩散找到回文字段&#x…

【Docker】使用Dev Container进行开发

工作区 Dev Container 设置 新建一个文件夹 ./devcontainer 然后下面放 devcontainer.json 然后安装 vscode dev container 插件,然后 CtrlShiftP 启动 Container {"name": "PyTorch-Julia Development","image": "x66ccff/p…

浅谈操作系统与初识Linux

一、Linux操作系统的出现 1.1操作系统的出现以及相关的四个要素 1.2最早出现的操作系统及其创始人 起初,IBM为了让计算机可以以更低技术成本进行使用,以此来售卖计算机; 为计算机搭载上了Unix操作系统,Unix由肯汤普森用汇编语…

ElasticSearch下

DSL查询 叶子查询:在特定字段里查询特定值,属于简单查询,很少单独使用复合查询:以逻辑方式组合多个叶子查询或更改叶子查询的行为方式 在查询后还可以对查询结果做处理: 排序:按照1个或多个字段做排序分页…

牛客----mysql

查找除复旦大学的用户信息_牛客题霸_牛客网 题目:现在运营想要查看除复旦大学以外的所有用户明细包括的字段有 device_id、gender、age、university,请你取出相应数据 示例:user_profile iddevice_idgenderageuniversityprovince12138male…

Android SystemUI——CarSystemBar车载状态栏(九)

上一篇文章我们介绍了车载开发中的 CarSystemUI,而车载开发中的状态栏也被 CarSystemBar 所取代,这里我们就来看看一下车载系统中的状态栏——CarSystemBar。 一、车载状态栏创建 1、CarSystemBar 源码位置:/packages/apps/Car/SystemUI/src/com/android/systemui/car/sy…

java根据模板导出word,并在word中插入echarts相关统计图片以及表格

引入依赖创建word模板创建ftl模板文件保存的ftl可能会出现占位符分割的问题,需要处理将ftl文件中的图片的Base64删除,并使用占位符代替插入表格,并指定表格的位置在图片下方 Echarts转图片根据模板生成word文档DocUtil导出word文档 生成的wor…

链式前向星的写法

【图论02】动画说图的三种保存方式 降低理解门槛 邻接表 链式前向星 邻接矩阵_哔哩哔哩_bilibili 杭电ACM刘老师-算法入门培训-第12讲-拓扑排序及链式前向星_哔哩哔哩_bilibili 图论003链式前向星_哔哩哔哩_bilibili(链式前向星的遍历) head数组的下标…

Trie(算法版)

#include <iostream>using namespace std;const int N100010; int son[N][26],cnt[N],idx; //son记录trie数&#xff0c;cnt记录每个词出现的次数&#xff0c;idx记录每个字符所占⽤的下标//加入字符串 void add(char str[]){//idx 0既表⽰根节点也表⽰空节点int p 0;fo…

软件工程导论

第 1 章 软件工程学概述&#xff1a;介绍了软件危机的表现、产生原因及消除途径&#xff0c;阐述了软件工程的定义、基本原理和方法学&#xff0c;还讲解了软件生命周期和软件过程的相关概念&#xff0c;包括瀑布模型、快速原型模型等多种软件开发模型当当。第 2-8 章 软件生命…

想品客老师的第一天:值类型使用

前面两章的摘要 ECMAscript&#xff08;也就是ES&#xff09;是JavaScript的一个标准&#xff0c;就像c的c11和c99一样&#xff0c;几把的一年出一套标准 freeze()是一个对象方法&#xff0c;表示锁定、固定一个对象不可改变&#xff08;因为const对于标量不可变&#xff0c;…

容器渗透横向

本质上要获得 1.获得容器IP段 2.获得主机IP段 3.获得本机IP 4.通过CNI或Docker0等扫描本机端口 Flannel 容器信息 rootubuntu-linux-22-04-desktop:/home/parallels/Desktop# k get po -A -o wide NAMESPACE NAME …

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…

解决本地运行MR程序访问权限问题

文章目录 1. 提出问题2. 解决问题2.1 临时解决方案2.2 永久解决方案 3. 小结 1. 提出问题 运行DeduplicateIPsDriver类&#xff0c;抛出如下异常&#xff1a; 该错误信息表明在尝试运行 DeduplicateIPsDriver 类时&#xff0c;遇到了 HDFS&#xff08;Hadoop 分布式文件系统&a…

【学习总结|DAY032】后端Web实战:登录认证

在 Web 后端开发中&#xff0c;登录认证是保障系统安全和用户数据隐私的关键环节。本文将结合实际开发案例&#xff0c;深入探讨登录功能与登录校验的实现思路和技术细节&#xff0c;希望能帮助读者更好地掌握这一重要知识点。 一、登录功能实现 1.1 思路分析 登录功能的核心…

html全局遮罩,通过websocket来实现实时发布公告

1.index.html代码示例 <div id"websocket" style"display:none;position: absolute;color:red;background-color: black;width: 100%;height: 100%;z-index: 100; opacity: 0.9; padding-top: 30%;padding-left: 30%; padding-border:1px; "onclick&q…

sqlmap使用手册

sqlmap使用手册 一、sqlmap简介二、sqlmap常用命令三、sqlmap使用示例四、注意事项sqlmap使用手册 sqlmap是一个开源的渗透测试工具,主要用于自动检测和利用SQL注入漏洞来接管数据库服务器。以下是对sqlmap的详细介绍和使用指南: 一、sqlmap简介 sqlmap具有强大的检测引擎和…

高通8255 Android STR 启动失败要因分析调查

目录 背景&#xff1a; 调查过程&#xff1a; 步骤1&#xff1a; slog2info | grep vmm_service 步骤2&#xff1a; slog2info | grep qvm 总结&#xff1a; 解决方案 背景&#xff1a; 调试高通8255 STR的STR过程中发现Android和QNX进入STR状态后&#xff0c;脱出STR时…

Linux UDP 编程详解

一、引言 在网络编程领域&#xff0c;UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;作为一种轻量级的传输层协议&#xff0c;具有独特的优势和适用场景。与 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff0…

数据增强方法及其工具

数据增强&#xff08;Data Augmentation&#xff09;是指在训练深度学习模型时&#xff0c;通过对现有数据进行一系列变换&#xff0c;从而生成新的样本。数据增强有助于增加数据的多样性&#xff0c;减少过拟合&#xff0c;提升模型的泛化能力&#xff0c;尤其是在数据量有限的…