跳至主要内容

升级到 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 的新索引类型:Hash(在版本 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 现在是对象

对于 JSON 列,JavaScript null 是模棱两可的,因此 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. 如果您将动态 JSON 传递到 Prisma Client 中的 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。
  • 您可以使用 @prisma/internals 中的 getDmmf() 来访问 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 的录制直播。