跳至主内容

升级到 Prisma ORM 5

Prisma ORM 5.0.0 引入了许多变更,包括使用我们新的 JSON Protocol,这使得 Prisma Client 默认情况下更快。这些变更的完整列表可以在我们的发布说明中找到

本指南解释了升级可能如何影响您的应用程序,并提供了如何处理 Prisma ORM 5 中的破坏性变更的说明。

prisma@prisma/client 包升级到版本 5

要从早期版本升级到 Prisma ORM 5,您需要更新 prisma@prisma/client 这两个包。

npm install @prisma/client@5
npm install -D prisma@5
危险

在升级之前,请检查下面的每一项破坏性变更,了解升级可能如何影响您的应用程序。

版本变更

Prisma ORM 5 包含 Node.js、TypeScript 和 PostgreSQL 的一些最低版本变更。要使用 Prisma 5.0.0 及更高版本,您需要至少满足以下最低版本要求:请参阅我们的系统要求了解所有最低版本要求。

Node.js 最低版本变更

从 Prisma ORM 5.0.0 版本开始,支持的 Node.js 最低版本为 16.13.0。如果您的项目使用早期版本的 Node.js,则需要升级它。

警告

Node.js v16.x 将于 2023 年 9 月 11 日到达生命周期结束,以便与 OpenSSL 1.1.1 的生命周期结束同步。因此,我们建议升级到当前的 Node.js LTS 版本,v18.x。请注意,Prisma ORM 5 将是 Prisma ORM 支持 Node.js v16 的最后一个主要版本。

TypeScript 最低版本变更

从 Prisma ORM 5.0.0 版本开始,支持的 TypeScript 最低版本为 4.7。如果您的项目使用早期版本的 TypeScript,则需要升级它。

PostgreSQL 最低版本变更

从 Prisma ORM 5.0.0 版本开始,支持的 PostgreSQL 最低版本为 9.6。如果您的项目使用早期版本的 PostgreSQL,则需要升级它。

警告

虽然 Prisma ORM 支持 PostgreSQL 9.6 及更高版本,但我们强烈建议更新到当前受支持且仍在接收更新的版本。请查看PostgreSQL 的版本控制策略以确定当前支持哪些版本。

Prisma Client 内嵌 SQLite 版本更新

随着 Prisma ORM 5.0.0 版本的发布,我们将内嵌的 SQLite 版本从 3.35.4 升级到了 3.41.2。我们没有发现任何破坏性变更,也不预期用户项目需要进行任何变更,但如果您正在使用 SQLite,特别是使用可能超出 Prisma ORM 功能的原始查询,请务必查看SQLite 的更新日志

主要变更

本节概述了 Prisma ORM 5 中的主要破坏性变更。

移除 rejectOnNotFound 参数

在 Prisma ORM 5 中,已移除弃用的参数 rejectOnNotFound。根据您的项目是按查询使用 rejectOnNotFound 还是全局使用,会有不同的更新代码方式。

如果您是按查询使用 rejectOnNotFound 参数,请按照我们关于在查询级别更新代码的步骤进行操作。

如果您是在客户端级别设置了 rejectOnNotFound 参数,则需要按照关于在客户端级别更新代码的步骤进行操作。

jsonProtocol 退出预览阶段

jsonProtocol 预览特性现已正式发布(GA)。与我们之前的基于 GraphQL 的协议相比,这项新协议显著提高了启动时间。升级到 Prisma ORM 5 时,请确保从您的预览特性中移除 jsonProtocol(如果已添加)。

Prisma ORM 4 及更低版本

generator client {
provider = "prisma-client-js"
previewFeatures = ["jsonProtocol"]
}

Prisma ORM 5

generator client {
provider = "prisma-client-js"
}

请查阅我们的jsonProtocol 变更指南,了解如何更新您的应用程序以适应 Prisma ORM 5 中的新协议。您需要

移除数组快捷方式

Prisma ORM 5 停止支持多种“数组快捷方式”。这些快捷方式是一种将单个元素作为值添加到基于数组的操作符的方法,而不是将该单个元素包裹在一个数组中。为了使我们的类型更一致和逻辑化,并符合新的 JSON Protocol,我们现在要求这些操作符使用数组值。

在大多数情况下,修复很简单,只需将现有值包裹在一个数组中即可。在 Prisma ORM 5 中移除的快捷方式包括

虽然 ORinnotIn 操作符受到影响,但 ANDNOT 不受此变更影响。

连接到 CockroachDB 数据库时现在需要使用 cockroachdb provider

随着 Prisma ORM 5.0.0 版本的发布,我们要求在连接到 CockroachDB 数据库时使用 cockroachdb provider。之前我们也接受 postgresql,但我们正在移除该选项。

如果您之前使用原生数据库类型以及 postgresql provider,您需要将您的数据库从 PostgreSQL 基线化到 CockroachDB

  1. 备份您现有的 schema.prisma 文件(例如,使用版本控制)
  2. 将您的 datasource provider 从 postgresql 更新为 cockroachdb
  3. 使用 npx prisma db pull --force 以覆盖您现有的 Prisma schema(包括原生类型),使其与您的 CockroachDB 实例上的相符。
  4. 检查您的 Prisma schema 备份与通过 db pull 生成的新 Prisma schema 之间的差异。您可以直接使用新 schema,也可以更新它以包含您偏好的缩进、注释等。
  5. 删除您现有的迁移文件。我们将执行一次基线操作,以使您的本地设置与您现有的 CockroachDB 实例一致。
  6. 执行基线化步骤。完成这些步骤后,您就成功地从 postgresql provider 迁移到了 cockroachdb provider!

从生成的客户端中移除 runtime/index.js

runtime/index.js 文件已从 Prisma Client 中移除。

使用来自 @prisma/client/runtime 的公共 API

@prisma/client/runtime 导入在 Prisma ORM 5 中不再可用。如果您之前使用此命名空间中可用的公共 API,您可以改为导入 Prisma 并访问它们。例如

import { Decimal, NotFoundError } from '@prisma/client/runtime'
const num = new Decimal(24.454545)
const notFound = new NotFoundError()

需要更改为

import { Prisma } from '@prisma/client'
const num = new Prisma.Decimal(24.454545)
const notFound = new Prisma.NotFoundError()

使用特定运行时的私有 API

我们强烈不建议使用内部私有 API,因为它们可能会在没有警告的情况下更改,并且不保证得到支持。如果您的使用需要之前可用的私有 API,请在GitHub 上联系我们。

生成的类型变更

RelationFilterInput 变更以考虑可空性

在 Prisma ORM 5 之前,存在一个长期存在的 bug,导致可空的逆向关系在我们的生成类型中未被标记为可空。例如,考虑以下 schema

model User {
id Int @id

addressId Int @unique
address Address @relation(fields: [addressId], references: [id])

post Post[]
}

model Address {
id Int @id

user User?
}

model Post {
id Int @id

userId Int
user User @relation(fields: [userId], references: [id])
}

在生成的类型中,Address.userPost.user 会使用相同的类型 UserRelationFilter。这显然是意外的,因为 Address.user 是可空的,而 Post.user 不是。在 Prisma ORM 5 中,Address.user 的类型将是 UserNullableRelationFilter,解决了这个问题。

如果在您的代码中导入了生成的类型,您需要更新此类实例以使用新的 Nullable 类型。

UncheckedUpdateManyInput 变更以避免名称冲突

在某些情况下,当一个模型有两个外键指向另外两个模型,并且这两个模型对逆向关系使用相同的属性名称时,可能发生名称冲突。例如,以下 schema

model Invoice {
InvoiceId Int @id @default(autoincrement())

invoice_items InvoiceItem[]
}

model InvoiceItem {
InvoiceLineId Int @id @default(autoincrement())

InvoiceItemInvoiceId Int @map("InvoiceId")
invoices Invoice @relation(fields: [InvoiceItemInvoiceId], references: [InvoiceId])

TrackId Int
tracks Track @relation(fields: [TrackId], references: [TrackId])
}

model Track {
TrackId Int @id @default(autoincrement())
Name String

invoice_items InvoiceItem[]
}

会导致 InvoiceItem 上两个关系之间发生名称冲突。逆向关系,即 Invoice.invoice_itemsTrack.invoice_items,都将获得 InvoiceItemUncheckedUpdateManyWithoutInvoice_itemsInput 类型。在 Prisma ORM 5 中,这个问题得到了解决,Prisma Client 将分别生成 InvoiceItemUncheckedUpdateManyWithoutInvoicesInputInvoiceItemUncheckedUpdateManyWithoutTracksInput

如果在您的代码中导入了生成的类型,您需要将此类实例更新为更正后的类型。

其他变更

升级到 Prisma ORM 5 后,以下变更可能导致应用程序初始时抛出错误消息。幸运的是,它们很容易解决,因为底层功能已经移除了一段时间,或者变更只是简单的字符串替换。

移除弃用的 Prisma CLI 标志

已移除几个弃用的 CLI 标志。以下所有标志都来自以前的 API,不再需要

  • db execute, db seeddb diff 中使用的 --preview-feature
  • migrate 中使用的 --experimental--early-access-feature
  • db push 中使用的 --force/-f
  • db pull 中使用的 --experimental-reintrospection--clean

db push --force 的过时用法可以替换为新的实现 db push --accept-data-loss

所有其他标志都来自以前的 API,不再需要。

从 library 引擎中移除 beforeExit hook

beforeExit hook 已从 Prisma ORM library 引擎中移除。虽然此功能对于 Prisma ORM binary 引擎仍然需要用于执行最后时刻的查询或执行关闭相关操作,但它在 library 引擎中相比原生 Node.js exit hooks 没有提供额外优势。我们建议改用内置的 Node.js exit 事件。

使用 Prisma ORM 4 的以下代码

const exitHandler = () => {
// your exit handler code
}

prisma.$on('beforeExit', exitHandler)

可以改为

const exitHandler = () => {
// your exit handler code
}

process.on('exit', exitHandler)
process.on('beforeExit', exitHandler)
process.on('SIGINT', exitHandler)
process.on('SIGTERM', exitHandler)
process.on('SIGUSR2', exitHandler)

如果您在 NestJS 中使用 beforeExit hook,您可以通过移除服务中的自定义 enableShutdownHooks 方法来升级到 Prisma ORM 5

"prisma.service.ts"
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect()
}

- async enableShutdownHooks(app: INestApplication) {
- this.$on('beforeExit', async () => {
- await app.close()
- })
- }
}

如果需要处理生命周期事件,请改用 NestJS 中内置的 enableShutdownHooks 方法

"main.ts"
- prismaService.enableShutdownHooks(app)
+ app.enableShutdownHooks()

移除弃用的 prisma2 可执行文件

当我们发布 Prisma ORM 2 时,使用 prisma2 可执行文件是为了与 Prisma 1 进行区分。在后来的版本中,prisma2 cli 接管了 prisma 可执行文件名称。

毋庸置疑,prisma2 可执行文件已弃用一段时间,现在已被移除。如果您的脚本使用 prisma2 作为 Prisma CLI,请将其替换为简单的 prisma

移除弃用的 experimentalFeatures 属性

gensator 块的previewFeatures 字段以前叫做 experimentalFeatures。我们正在移除这个弃用属性。

在 Prisma ORM 5 中,您需要手动将 experimentalFeatures 的引用更新为 previewFeatures,或者使用 Prisma VSCode 扩展中的新代码操作。

migration-engine 更名为 schema-engine

负责 prisma migrateprisma db 等命令的引擎已从 migration-engine 更名为 schema-engine,以更好地描述其用途。对于许多用户来说,不需要进行任何更改。但是,如果您需要明确包含或排除此引擎文件,或出于其他原因引用引擎名称,则需要更新您的代码引用。

使用 Serverless Framework 的示例

我们见过的一个示例是使用 Serverless Framework 的项目。在这些情况下,您需要更新任何引用 migration-engine 的模式,改为引用 schema-engine

package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-rhel-*'
- '!node_modules/prisma/libquery_engine-*'
-- '!node_modules/prisma/migration-engine-*'
-- '!node_modules/prisma/schema-engine-*'
Serverless Framework 模式建议

我们文档中推荐的规则不受此变更影响,因为它排除了所有不需要的引擎文件。

package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-rhel-*'
- '!node_modules/prisma/libquery_engine-*'
-- '!node_modules/@prisma/engines/**'

尽情享受 Prisma ORM 5!