跳到主要内容

升级到 Prisma ORM 4

当您从早期 Prisma ORM 版本升级时,Prisma ORM 4 引入了许多重大更改。本指南解释了此升级可能如何影响您的应用程序,并提供了有关如何处理任何更改的说明。

重大更改

本节概述了 Prisma ORM 4 中的重大更改,这些更改分为影响 Prisma Schema 和 Prisma Client 的一般更改Schema 更改Client 更改

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

升级您的 Prisma Schema

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

升级您对 Prisma Client 的使用

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

享受 Prisma ORM 4!

一般更改

本节包括影响 Prisma Schema 和 Prisma Client 的更改。

Node.js 最低版本更改

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

有关所有最低版本要求,请参阅我们的系统要求

Schema 更改

本节包括影响 Prisma Schema 的更改。

索引配置

在 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 schema 中表示的任何配置。

有关更多详细信息,请参阅我们的索引配置文档的从以前版本升级部分。

标量列表默认值

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

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 schema 中表示的任何默认值。

一对一关系的显式 @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 schema 中的验证错误。

  3. 使用 prisma db push for MongoDB 或 prisma migrate dev for MySQL 将更改推送到您的数据库。

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

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

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

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 模型之间的一对一关系的示例中,必须将 @unique 属性添加到 email 字段

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 schema 中的验证错误。或者,如果您有一个最新的实时数据库,运行 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 schema 中的验证错误。或者,如果您有一个最新的实时数据库,运行 npx prisma db pull 将自动删除 references 参数。

更好的字符串文字语法

您的 Prisma Schema 中的字符串文字现在需要遵循与 JSON 中的字符串相同的规则。这主要更改了一些特殊字符的转义。更多详细信息可以在 JSON 规范JSON 网站 中找到。

升级路径

对于某些现有 schema 来说,这是一个重大更改。升级到 Prisma ORM 4 后,错误转义的字符将触发验证错误。要升级,您需要

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

Client 更改

本节包括影响 Prisma Client 的更改。

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

在 3.14.x 和 3.15.x 版本中,原始查询类型映射通过 improvedQueryRaw 预览功能提供。在 4.0.0 版本中,我们已将原始查询类型映射正式发布。您无需使用 improvedQueryRaw 即可在 4.0.0 及更高版本中获得此功能。

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

示例查询和响应

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 版本中,我们已将原始查询类型映射正式发布。您无需使用 improvedQueryRaw 即可在 4.0.0 及更高版本中获得此功能。

在 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 版本中,我们已将原始查询类型映射正式发布。您无需使用 improvedQueryRaw 即可在 4.0.0 及更高版本中获得此功能。

Prisma ORM 将 JavaScript 整数作为 INT8 发送到 PostgreSQL。这可能会与您的用户定义函数冲突,这些函数仅接受 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 的字段可能在您的 schema 中不是可为空的。因此,文字 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 是一个弱类型数据库。如果您的 schema 有一个类型为 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 的录制直播