跳至主要内容

升级到 Prisma ORM 4

从较早的 Prisma ORM 版本升级到 Prisma ORM 4 时,会引入一些**重大变更**。本指南说明了此升级可能如何影响您的应用程序,并提供有关如何处理任何变更的说明。

重大变更

本节概述了 Prisma ORM 4 中的重大变更,并根据影响 Prisma 架构和 Prisma Client 的一般变更架构变更客户端变更进行分组。

我们建议您首先解决任何 Prisma 架构验证错误,然后将您的数据库拉取以反映新的 Prisma 架构功能,最后修复 Prisma Client 中的任何类型错误并通过运行您的测试套件进行验证。

升级您的 Prisma 架构

  1. 仔细浏览变更列表,并检查您是否受到重大变更的影响。
  2. 查看 Prisma 架构验证错误(通过npx prisma validate或通过 Prisma VS Code 扩展)。
    1. 如果您没有验证错误,请继续执行步骤 3。
    2. 如果您有验证错误
      1. 尝试将验证错误映射到以下列表中的变更,以了解哪个变更导致了无效的 Prisma 架构,并阅读链接的说明,了解如何升级。它只能来自
  3. 重复此操作,直到您的 Prisma 架构有效。
  4. 运行npx prisma db pull将 Prisma 架构升级到所有新功能(例如extendedIndexes)。
  5. 查看 Prisma 架构的变更并验证其有效性。
  6. 继续执行 Prisma Client 步骤。

升级您对 Prisma Client 的使用

  1. 仔细浏览变更列表,以了解您是否受到重大变更的影响。
    1. 如果是,请阅读详细的升级说明。
    2. 如果不是,请继续执行 2。
  2. Prisma Client 中的一些 API 变更会影响运行时行为,因此请运行您的测试套件。

尽情享受 Prisma ORM 4!

一般变更

本节包含影响 Prisma 架构和 Prisma Client 的变更。

Node.js 最低版本变更

从 Prisma ORM 版本 4.0.0 开始,我们支持的 Node.js 的最低版本为 14.17.x。如果您使用的是较早版本的 Node.js,则需要进行更新。

请查看我们的系统要求,了解所有最低版本要求。

架构变更

本节包含影响 Prisma 架构的变更。

索引配置

在 Prisma ORM 4 中,extendedIndexes预览功能将成为通用可用功能。这包括以下索引配置选项

  • MySQL 索引、唯一约束和主键约束的长度配置(在版本 3.5.0 及更高版本中处于预览阶段)
  • 索引、唯一约束和主键约束的排序顺序配置(在版本 3.5.0 及更高版本中处于预览阶段)
  • PostgreSQL 的新索引类型:哈希(在版本 3.6.0 及更高版本中处于预览阶段)和 GIN、GiST、SP-GiST 和 BRIN(在版本 3.14.0 及更高版本中处于预览阶段)
  • SQL Server 的索引聚类(在版本 3.13.0 及更高版本中处于预览阶段)

请查看我们有关索引配置的文档,以了解有关这些功能的更多详细信息。

升级路径

如果您之前是在数据库级别配置这些属性,则所有这些都可能是重大变更。在这种情况下,您需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包
  2. 之后运行npx prisma db pull以检索任何现有的索引和约束配置。这需要在运行任何npx prisma db pushnpx prisma migrate dev命令之前完成,否则您可能会丢失在数据库中定义但在 Prisma 架构中未表示的任何配置。

有关更多详细信息,请查看索引配置文档中的从先前版本升级部分。

标量列表默认值

对于支持标量列表的数据库连接器(PostgreSQL、CockroachDB 和 MongoDB),Prisma ORM 4 引入了使用@default属性在 Prisma 架构中设置默认值的功能

model User {
id Int @id @default(autoincrement())
posts Post[]
favoriteColors String[] @default(["red", "yellow", "purple"])
}
升级路径

如果您之前在数据库级别为标量列表定义了默认值,则这是一个重大变更。在这种情况下,您需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包
  2. 之后运行npx prisma db pull以检索任何现有的索引和约束配置。这需要在运行任何npx prisma db pushnpx prisma migrate dev命令之前完成,否则您可能会丢失在数据库中定义但在 Prisma 架构中未表示的任何默认值。

一对一关系上的显式@unique约束

在 Prisma ORM 4 中使用一对一关系时,您需要在关系标量字段中显式添加@unique属性。例如,对于UserProfile模型之间的一对一关系,您需要在profileId字段中添加@unique属性

model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id])
profileId Int? @unique // <-- include this explicitly
}

model Profile {
id Int @id @default(autoincrement())
user User?
}
升级路径

升级到 Prisma ORM 4 后,任何一对一关系如果没有在关系标量上添加@unique属性,都会触发验证错误。要进行升级,您需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包

  2. 通过在数据模型中添加显式@unique@id属性,手动修复 Prisma 架构中的验证错误。

  3. 使用prisma db push(对于 MongoDB)或prisma migrate dev(对于 MySQL)将变更推送到数据库。

强制使用@unique@id属性以用于一对一和一对多关系(MySQL 和 MongoDB)

在 Prisma ORM 4 中使用一对一和一对多关系时,您需要在关系字段上使用@unique属性,以确保关系的单一侧(或双方)只有一个记录。现在,MySQL 和 MongoDB 强制执行此操作,使其与其他连接器保持一致。缺少@unique属性现在会触发验证错误。

在以下UserPost模型之间一对多关系的示例中,必须在email字段中添加@unique属性

model User {
id Int @id @default(autoincrement())
email String @unique // <-- we enforce this attribute
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}

在以下UserProfile模型之间一对一关系的示例中,必须在email字段中添加@unique属性

model User {
id Int @id @default(autoincrement())
email String @unique // <- we enforce this unique attribute
profile Profile @relation(fields: [profileId], references: [id])
profileId Int
}

model Profile {
id Int @id @default(autoincrement())
userEmail String? @unique
user User?
}
升级路径

升级到 Prisma ORM 4 后,任何一对一或一对多关系如果没有在关系字段上添加@unique@id属性,都会触发验证错误。要进行升级,您需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包
  2. 手动修复 Prisma 架构中的验证错误。或者,如果您有最新的实时数据库,运行npx prisma db pull将自动添加@unique属性。

禁止对隐式多对多关系使用references语法

在 Prisma ORM 4 中使用隐式多对多关系时,您将无法再使用references参数,该参数以前是可选的。例如,以下关系现在会触发验证错误

schema.prisma
model Post {
id Int @id @default(autoincrement())
categories Category[] @relation("my-relation", references: [id]) // <-- validation error
}

model Category {
id Int @id @default(autoincrement())
posts Post[] @relation("my-relation", references: [id]) // <-- validation error
}

您可以改为编写

schema.prisma
model Post {
id Int @id @default(autoincrement())
categories Category[] @relation("my-relation")
}

model Category {
id Int @id @default(autoincrement())
posts Post[] @relation("my-relation")
}

这是因为references的唯一有效值为id,因此删除此参数可以更清楚地表明哪些可以更改,哪些不能更改。

升级路径

升级到 Prisma ORM 4 后,任何具有references参数的隐式多对多关系都会触发验证错误。要进行升级,您需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包
  2. 手动修复 Prisma 架构中的验证错误。或者,如果你有一个最新的实时数据库,运行 npx prisma db pull 将会自动移除 references 参数。

字符串字面量的语法改进

你现在 Prisma 架构中的字符串字面量需要遵循与 JSON 中字符串相同的规则。这主要改变了一些特殊字符的转义方式。更多详情可以在 JSON 规范 或者在 JSON 网站 上找到。

升级路径

这对一些现有的架构来说是一个重大变更。在你升级到 Prisma ORM 4 之后,错误转义的字符将触发一个验证错误。为了升级,你需要

  1. 按照这些说明升级到新的 Prisma ORM 4 包
  2. 手动修复 Prisma 架构中的验证错误。

客户端变更

本节包含影响 Prisma Client 的变更。

原始查询类型映射:标量值现在被反序列化为它们的正确 JavaScript 类型

在 3.14.x 和 3.15.x 版本中,原始查询类型映射 可以使用 improvedQueryRaw 预览功能获得。在 4.0.0 版本中,我们已经将原始查询类型映射设为通用可用。在 4.0.0 及更高版本中,你不需要使用 improvedQueryRaw 来获得此功能。

原始查询现在将标量值反序列化为它们对应的 JavaScript 类型。请注意,Prisma ORM 从值本身而不是从 Prisma 架构类型中推断类型。

示例查询和响应

const res =
await prisma.$queryRaw`SELECT bigint, bytes, decimal, date FROM "Table";`
console.log(res) // [{ bigint: BigInt("123"), bytes: Buffer.from([1, 2]), decimal: new Prisma.Decimal("12.34"), date: Date("<some_date>") }]
升级路径

从 4.0.0 版本开始,queryRawqueryRawUnsafe 返回的一些数据类型不同,如下所示

数据类型4.0.0 版本之前4.0.0 版本及之后
DateTime作为 String 返回作为 Date 返回
Numeric作为 Float 返回作为 Decimal 返回
Bytes作为 String 返回作为 Buffer 返回
Int64作为 Integer 返回作为 BigInt 返回

如果你使用 queryRawqueryRawUnsafe 来返回上述任何数据类型,那么你必须更改代码以处理新的类型。

例如,如果你返回 DateTime 数据,那么你需要考虑以下几点

  • 你不再需要为返回的数据手动实例化 DateTime 对象。
  • 如果你的代码当前使用的是返回的 String 数据,那么你现在需要将 DateTime 对象转换为 String

你必须对上表中其他数据类型进行等效的代码更改。

原始查询映射:PostgreSQL 类型转换

在 3.14.x 和 3.15.x 版本中,原始查询类型映射 可以使用 improvedQueryRaw 预览功能获得。在 4.0.0 版本中,我们已经将原始查询类型映射设为通用可用。在 4.0.0 及更高版本中,你不需要使用 improvedQueryRaw 来获得此功能。

在 4.0.0 版本之前,许多 PostgreSQL 类型转换不起作用。我们已经收紧了类型强制规则,以便所有类型转换现在都可以正常工作。因此,一些隐式转换现在失败。

升级路径

我们建议你重新测试你对 $queryRaw 的使用,以确保你传递到原始查询中的类型与 PostgreSQL 期望的类型匹配。

例如,在 4.0.0 版本中,以下查询失败

await prisma.$queryRaw`select length(${42});`
// ERROR: function length(integer) does not exist
// HINT: No function matches the given name and argument types. You might need to add explicit type casts.

这是因为 PostgreSQL 的 length 函数期望 text 作为输入。Prisma ORM 以前会默默地将 42 强制转换为 text,但在 4.0.0 版本中不会这样做。为了修复这个问题,请显式地将 42 强制转换为 text,如下所示

await prisma.$queryRaw`select length(${42}::text);`

原始查询映射:PostgreSQL 和 JavaScript 整数

在 3.14.x 和 3.15.x 版本中,原始查询类型映射 可以使用 improvedQueryRaw 预览功能获得。在 4.0.0 版本中,我们已经将原始查询类型映射设为通用可用。在 4.0.0 及更高版本中,你不需要使用 improvedQueryRaw 来获得此功能。

Prisma ORM 将 JavaScript 整数发送到 PostgreSQL 作为 INT8。这可能会与你的用户定义函数冲突,这些函数只接受 INT4 作为输入。

升级路径

如果你使用 $queryRaw 或参数化的 $queryRawUnsafe 查询与 PostgreSQL 数据库交互,请执行以下操作之一

  • 将用户定义函数中所有整数的输入类型更新为 INT8,或者
  • 将查询参数中的所有整数强制转换为 INT4

DbNullJsonNullAnyNull 现在是对象

JavaScript null 对 JSON 列是模棱两可的,因此 Prisma ORM 使用 DbNullJsonNullAnyNull 来区分数据库 NULL 值和 JSON null 值。在 4.0.0 版本之前,DbNullJsonNullAnyNull 是字符串常量。从 4.0.0 版本开始,它们是对象。

有关更多信息,请参阅 按空值过滤

升级路径
  1. 如果你使用字面量字符串来处理这些值,那么你必须将它们替换为以下命名常量

    • DbNull:替换为 Prisma.DbNull
    • JsonNull:替换为 Prisma.JsonNull
    • AnyNull:替换为 Prisma.AnyNull

    如果你已经使用这些命名常量,那么你不需要采取任何措施。

  2. 如果你在将 Prisma.DbNull 作为 JSON 字段的值传递时遇到类型错误,那么这可能表明你的代码中存在错误,我们的类型在 4.0.0 版本之前没有捕获到这个错误。你尝试存储 DbNull 的字段可能在你的架构中不可为空。因此,一个字面量 DbNull 字符串被存储在数据库中而不是 NULL

  3. 当你使用 Prisma.DbNullPrisma.JsonNullPrisma.AnyNull 与 MongoDB 一起使用时,你可能会遇到类型错误或运行时验证错误。这在以前是不允许的,但在 Prisma ORM 4 之前被静默地接受了。你需要检查你的数据并将这些字段更改为 null

  4. 如果你在 Prisma Client 中将动态 JSON 传递给 JSON 列(例如 prisma.findMany({where: { jsonColumn: someJson } })),那么你必须检查 someJson 不能是字符串 "DBNull"、"JsonNull" 或 "AnyNull"。如果它是这些值中的任何一个,那么在 4.0.0 版本中,查询将返回不同的结果。

MongoDB 中复合类型上的默认字段

从 4.0.0 版本开始,如果你在以下所有条件都为真的情况下对复合类型执行数据库读取操作,那么 Prisma Client 将默认值插入结果中。

条件

  • 复合类型上的一个字段是必需的,并且
  • 此字段具有默认值,并且
  • 此字段不存在于返回的文档或文档中。

此行为现在与模型字段的行为一致。

要了解更多信息,请参阅 复合类型上必需字段的默认值

升级路径

如果你当前依赖于 null 的返回值,那么你需要重构你的代码以处理现在在 Prisma ORM 4 中返回的默认值。

SQLite 中大数字的舍入错误

SQLite 是一个类型松散的数据库。如果你的架构中有一个类型为 Int 的字段,那么 Prisma ORM 会阻止你插入大于整数的值。但是,没有什么可以阻止数据库直接接受更大的数字。这些手动插入的大数字在查询时会导致舍入错误。

为了避免这个问题,Prisma ORM 4.0.0 及更高版本会在数据从数据库中返回时检查数字,以验证它们是否在整数的范围内。如果一个数字不符合,那么 Prisma ORM 会抛出一个 P2023 错误,例如

Inconsistent column data: Conversion failed:
Value 9223372036854775807 does not fit in an INT column,
try migrating the 'int' column type to BIGINT
升级路径

如果你将 Prisma ORM 与 SQLite 一起使用,那么你需要找到所有查询 Int 字段的代码,并确保它能处理可能返回的任何 P2023 错误。

Prisma ORM 不再将 Prisma.dmmf.schema 导出到生成的 Prisma Client

从 4.0.0 版本开始,Prisma ORM 不再将 Prisma.dmmf.schema 导出到生成的 Prisma Client。这使得生成的 Prisma Client 更加高效,并且避免了一些与 Jest 相关的内存泄漏。

注意

  • 此更改不会影响 Prisma ORM 传递给生成器的 DMMF。
  • 你可以使用 getDmmf()@prisma/internals 中访问 schema 属性。
  • 我们仍然将 Prisma.dmmf.datamodel 导出到生成的 Prisma Client 中。

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

要从早期版本升级到 Prisma ORM 4,你需要更新 prisma@prisma/client 包。prisma@prisma/client 包都使用脱字符 ^ 在它们的版本号中安装。这允许升级到新的次要版本,但不允许升级到主要版本,以防范重大变更。

要忽略脱字符 ^ 并跨主要版本升级,你可以在使用 npmyarn 升级时使用 @4 标签

危险

在你升级之前,请检查每个 **重大变更** 以查看升级可能如何影响你的应用程序。

npm install prisma@4 @prisma/client@4

视频指南

有关升级过程的视频演示和升级场景示例,请观看我们关于升级到 Prisma ORM 4 的录制直播