跳到主要内容

升级到 Prisma ORM 5

Prisma ORM 5.0.0 引入了许多更改,包括使用我们新的 JSON 协议,这使得 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 日达到生命周期结束 (EOL),以便与 OpenSSL 1.1.1 的生命周期结束相一致。因此,我们建议升级到当前的 Node.js LTS,v18.x。请注意,Prisma ORM 5 将是最后一个支持 Node.js v16 的 Prisma ORM 主要版本。

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 协议,我们现在要求这些运算符使用数组值。

在大多数情况下,修复方法将像将现有值包装在数组中一样简单。Prisma ORM 5 中移除的快捷方式包括

虽然 ORinnotIn 运算符受到影响,但 ANDNOT 不受此更改的影响。

连接到 CockroachDB 数据库时,现在需要 cockroachdb 提供程序

在 Prisma ORM 5.0.0 版本中,我们要求在连接到 CockroachDB 数据库时使用 cockroachdb 提供程序。以前,我们也接受 postgresql,但我们正在删除该选项。

如果您正在使用 原生数据库类型 以及 postgresql 提供程序,您将需要基线化您的数据库,从 PostgreSQL 到 CockroachDB

  1. 备份您现有的 schema.prisma 文件(例如,使用版本控制)
  2. 将您的 datasource 提供程序从 postgresql 更新为 cockroachdb
  3. 使用 npx prisma db pull --force 以覆盖您现有的 Prisma schema(包括原生类型)为 CockroachDB 实例上的类型。
  4. 查看您的 Prisma schema 备份与 db pull 生成的新 Prisma schema 之间的更改。您可以按原样使用新 schema,也可以更新它以包含您喜欢的间距、注释等。
  5. 删除您现有的迁移。我们将执行基线化,以使您的本地设置与您现有的 CockroachDB 实例一致。
  6. 执行基线化步骤。完成这些步骤后,您将成功从 postgresql 提供程序迁移到 cockroachdb 提供程序!

从生成的客户端中移除 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 之前,存在一个长期存在的错误,该错误导致可为空的反向关系在我们生成的类型中未标记为可为空。例如,以下 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 executedb 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,并且不再需要。

从库引擎中移除 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

“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 可执行文件已被弃用一段时间,现在已被移除。如果您的脚本将 Prisma CLI 用作 prisma2,请将其替换为简单的 prisma

移除已弃用的 experimentalFeatures 属性

generator 块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!