升级到 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
- yarn
- pnpm
npm install @prisma/client@5
npm install -D prisma@5
yarn up prisma@5 @prisma/client@5
pnpm upgrade prisma@5 @prisma/client@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 预览功能现已正式发布。与我们之前的基于 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 中移除的快捷方式有:
虽然 OR、in 和 notIn 操作符受到影响,但 AND 和 NOT 不受此变更影响。
连接到 CockroachDB 数据库时现在需要 cockroachdb provider
在 Prisma ORM 5.0.0 版本中,我们要求连接到 CockroachDB 数据库时使用 cockroachdb provider。以前,我们也接受 postgresql,但现在我们正在移除该选项。
如果您之前使用了原生数据库类型以及 postgresql provider,您将需要将您的数据库从 PostgreSQL 基线化到 CockroachDB。
- 备份您现有的
schema.prisma文件(例如,使用版本控制) - 将您的
datasourceprovider 从postgresql更新为cockroachdb - 使用
npx prisma db pull --force以覆盖您现有的 Prisma schema(包括原生类型),使其与 CockroachDB 实例上的类型一致。 - 审查您的 Prisma schema 备份与
db pull生成的新 Prisma schema 之间的变更。您可以直接使用新 schema,也可以对其进行更新,以包含您偏好的间距、注释等。 - 删除您现有的迁移。我们将执行基线化,以使您的本地设置与现有 CockroachDB 实例保持一致。
- 执行基线化步骤。完成这些步骤后,您将成功从
postgresqlprovider 迁移到cockroachdbprovider!
从生成的客户端中移除 runtime/index.js
runtime/index.js 文件已从 Prisma Client 中移除。
使用 @prisma/client/runtime 中的公共 API
从 Prisma ORM 5 开始,不再支持从 @prisma/client/runtime 导入。如果您之前使用此命名空间中的公共 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.user 和 Post.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_items 和 Track.invoice_items,都将获得类型 InvoiceItemUncheckedUpdateManyWithoutInvoice_itemsInput。在 Prisma ORM 5 中,此问题已解决,Prisma Client 将分别生成 InvoiceItemUncheckedUpdateManyWithoutInvoicesInput 和 InvoiceItemUncheckedUpdateManyWithoutTracksInput。
如果您的代码中导入了生成的类型,您需要将此类实例更新为更正后的类型。
其他变更
以下变更可能导致应用程序在升级到 Prisma ORM 5 后最初抛出错误消息。幸运的是,它们很容易解决,因为底层功能已移除一段时间,或者变更只是简单的字符串替换。
移除废弃的 Prisma CLI 标志
几个已废弃的 CLI 标志已被移除。以下所有标志均来自旧 API,不再需要:
--preview-feature用于db execute、db seed和db diff--experimental和--early-access-feature用于migrate--force/-f用于db push--experimental-reintrospection和--clean用于db pull
过时的 db push --force 可以替换为新的实现 db push --accept-data-loss。
所有其他标志都来自旧版 API,不再需要。
从库引擎中移除 beforeExit 钩子
beforeExit 钩子已从 Prisma ORM 库引擎中移除。虽然此功能对于 Prisma ORM 二进制引擎仍然需要,以便运行最后的查询或执行关机相关操作,但它与库引擎中的原生 Node.js 退出钩子相比没有任何优势。我们建议改用内置的 Node.js 退出事件。
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 钩子,您可以通过移除服务中的自定义 enableShutdownHooks 方法来升级到 Prisma ORM 5。
@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 方法:
- prismaService.enableShutdownHooks(app)
+ app.enableShutdownHooks()
移除废弃的 prisma2 可执行文件
当我们发布 Prisma ORM 2 时,使用 prisma2 可执行文件是为了与 Prisma 1 区分。在后来的版本中,prisma2 cli 接管了 prisma 可执行文件的名称。
毋庸置疑,prisma2 可执行文件已经废弃了一段时间,现在已被移除。如果您的脚本使用 prisma2 作为 Prisma CLI,请将其替换为简单的 prisma。
移除废弃的 experimentalFeatures 属性
生成器块的 previewFeatures 字段以前名为 experimentalFeatures。我们正在移除该废弃属性。
在 Prisma ORM 5 中,您需要手动将 experimentalFeatures 的引用更新为 previewFeatures,或者使用 Prisma VSCode 扩展中的新代码操作。
migration-engine 重命名为 schema-engine
负责 prisma migrate 和 prisma 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!