升级到 Prisma ORM 4
从较早的 Prisma ORM 版本升级到 Prisma ORM 4 时,会引入一些**重大变更**。本指南说明了此升级可能如何影响您的应用程序,并提供有关如何处理任何变更的说明。
重大变更
本节概述了 Prisma ORM 4 中的重大变更,并根据影响 Prisma 架构和 Prisma Client 的一般变更、架构变更和客户端变更进行分组。
我们建议您首先解决任何 Prisma 架构验证错误,然后将您的数据库拉取以反映新的 Prisma 架构功能,最后修复 Prisma Client 中的任何类型错误并通过运行您的测试套件进行验证。
升级您的 Prisma 架构
- 仔细浏览变更列表,并检查您是否受到重大变更的影响。
- 查看 Prisma 架构验证错误(通过
npx prisma validate
或通过 Prisma VS Code 扩展)。- 如果您没有验证错误,请继续执行步骤 3。
- 如果您有验证错误
- 尝试将验证错误映射到以下列表中的变更,以了解哪个变更导致了无效的 Prisma 架构,并阅读链接的说明,了解如何升级。它只能来自
- 为 1:1 关系显式唯一约束
- 删除对在隐式多对多关系中使用
references
的支持 - 在 MySQL 和 MongoDB 的一对一和一对多关系的
references
参数中强制引用字段的唯一性 - 删除对未记录的
type
别名的支持 - 删除 SQLite URL 的
sqlite
协议 - 改进字符串文字的语法
- 尝试将验证错误映射到以下列表中的变更,以了解哪个变更导致了无效的 Prisma 架构,并阅读链接的说明,了解如何升级。它只能来自
- 重复此操作,直到您的 Prisma 架构有效。
- 运行
npx prisma db pull
将 Prisma 架构升级到所有新功能(例如extendedIndexes
)。 - 查看 Prisma 架构的变更并验证其有效性。
- 继续执行 Prisma Client 步骤。
升级您对 Prisma Client 的使用
- 仔细浏览变更列表,以了解您是否受到重大变更的影响。
- 如果是,请阅读详细的升级说明。
- 如果不是,请继续执行 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 及更高版本中处于预览阶段)
请查看我们有关索引配置的文档,以了解有关这些功能的更多详细信息。
升级路径
如果您之前是在数据库级别配置这些属性,则所有这些都可能是重大变更。在这种情况下,您需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 之后运行
npx prisma db pull
以检索任何现有的索引和约束配置。这需要在运行任何npx prisma db push
或npx prisma migrate dev
命令之前完成,否则您可能会丢失在数据库中定义但在 Prisma 架构中未表示的任何配置。
有关更多详细信息,请查看索引配置文档中的从先前版本升级部分。
标量列表默认值
对于支持标量列表的数据库连接器(PostgreSQL、CockroachDB 和 MongoDB),Prisma ORM 4 引入了使用@default
属性在 Prisma 架构中设置默认值的功能
- 关系型数据库
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
favoriteColors String[] @default(["red", "yellow", "purple"])
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
favoriteColors String[] @default(["red", "yellow", "purple"])
}
升级路径
如果您之前在数据库级别为标量列表定义了默认值,则这是一个重大变更。在这种情况下,您需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 之后运行
npx prisma db pull
以检索任何现有的索引和约束配置。这需要在运行任何npx prisma db push
或npx prisma migrate dev
命令之前完成,否则您可能会丢失在数据库中定义但在 Prisma 架构中未表示的任何默认值。
一对一关系上的显式@unique
约束
在 Prisma ORM 4 中使用一对一关系时,您需要在关系标量字段中显式添加@unique
属性。例如,对于User
和Profile
模型之间的一对一关系,您需要在profileId
字段中添加@unique
属性
- 关系型数据库
- MongoDB
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?
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
profile Profile? @relation(fields: [profileId], references: [id])
profileId String? @unique @db.ObjectId // <-- include this explicitly
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
user User?
}
升级路径
升级到 Prisma ORM 4 后,任何一对一关系如果没有在关系标量上添加@unique
属性,都会触发验证错误。要进行升级,您需要
-
按照这些说明升级到新的 Prisma ORM 4 包
-
通过在数据模型中添加显式
@unique
或@id
属性,手动修复 Prisma 架构中的验证错误。 -
使用
prisma db push
(对于 MongoDB)或prisma migrate dev
(对于 MySQL)将变更推送到数据库。
强制使用@unique
或@id
属性以用于一对一和一对多关系(MySQL 和 MongoDB)
在 Prisma ORM 4 中使用一对一和一对多关系时,您需要在关系字段上使用@unique
属性,以确保关系的单一侧(或双方)只有一个记录。现在,MySQL 和 MongoDB 强制执行此操作,使其与其他连接器保持一致。缺少@unique
属性现在会触发验证错误。
在以下User
和Post
模型之间一对多关系的示例中,必须在email
字段中添加@unique
属性
- 关系型数据库
- MongoDB
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])
}
model User {
id Int @id @default(auto()) @map("_id") @db.ObjectId
email String @unique // <-- we enforce this attribute
posts Post[]
}
model Post {
id Int @id @default(auto()) @map("_id") @db.ObjectId
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}
在以下User
和Profile
模型之间一对一关系的示例中,必须在email
字段中添加@unique
属性
- 关系型数据库
- MongoDB
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?
}
model User {
id Int @id @default(auto()) @map("_id") @db.ObjectId
email String @unique // <- we enforce this unique attribute
profile Profile @relation(fields: [profileId], references: [id])
profileId Int @db.ObjectId
}
model Profile {
id Int @id @default(auto()) @map("_id") @db.ObjectId
userEmail String? @unique
user User? @relation(fields: [userEmail], references: [email])
}
升级路径
升级到 Prisma ORM 4 后,任何一对一或一对多关系如果没有在关系字段上添加@unique
或@id
属性,都会触发验证错误。要进行升级,您需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 手动修复 Prisma 架构中的验证错误。或者,如果您有最新的实时数据库,运行
npx prisma db pull
将自动添加@unique
属性。
禁止对隐式多对多关系使用references
语法
在 Prisma ORM 4 中使用隐式多对多关系时,您将无法再使用references
参数,该参数以前是可选的。例如,以下关系现在会触发验证错误
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
}
您可以改为编写
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
参数的隐式多对多关系都会触发验证错误。要进行升级,您需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 手动修复 Prisma 架构中的验证错误。或者,如果你有一个最新的实时数据库,运行
npx prisma db pull
将会自动移除references
参数。
字符串字面量的语法改进
你现在 Prisma 架构中的字符串字面量需要遵循与 JSON 中字符串相同的规则。这主要改变了一些特殊字符的转义方式。更多详情可以在 JSON 规范 或者在 JSON 网站 上找到。
升级路径
这对一些现有的架构来说是一个重大变更。在你升级到 Prisma ORM 4 之后,错误转义的字符将触发一个验证错误。为了升级,你需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 手动修复 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 版本开始,queryRaw
或 queryRawUnsafe
返回的一些数据类型不同,如下所示
数据类型 | 4.0.0 版本之前 | 4.0.0 版本及之后 |
---|---|---|
DateTime | 作为 String 返回 | 作为 Date 返回 |
Numeric | 作为 Float 返回 | 作为 Decimal 返回 |
Bytes | 作为 String 返回 | 作为 Buffer 返回 |
Int64 | 作为 Integer 返回 | 作为 BigInt 返回 |
如果你使用 queryRaw
或 queryRawUnsafe
来返回上述任何数据类型,那么你必须更改代码以处理新的类型。
例如,如果你返回 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
。
DbNull
、JsonNull
和 AnyNull
现在是对象
JavaScript null
对 JSON 列是模棱两可的,因此 Prisma ORM 使用 DbNull
、JsonNull
和 AnyNull
来区分数据库 NULL
值和 JSON null
值。在 4.0.0 版本之前,DbNull
、JsonNull
和 AnyNull
是字符串常量。从 4.0.0 版本开始,它们是对象。
有关更多信息,请参阅 按空值过滤。
升级路径
-
如果你使用字面量字符串来处理这些值,那么你必须将它们替换为以下命名常量
DbNull
:替换为Prisma.DbNull
JsonNull
:替换为Prisma.JsonNull
AnyNull
:替换为Prisma.AnyNull
如果你已经使用这些命名常量,那么你不需要采取任何措施。
-
如果你在将
Prisma.DbNull
作为 JSON 字段的值传递时遇到类型错误,那么这可能表明你的代码中存在错误,我们的类型在 4.0.0 版本之前没有捕获到这个错误。你尝试存储DbNull
的字段可能在你的架构中不可为空。因此,一个字面量DbNull
字符串被存储在数据库中而不是NULL
。 -
当你使用
Prisma.DbNull
、Prisma.JsonNull
或Prisma.AnyNull
与 MongoDB 一起使用时,你可能会遇到类型错误或运行时验证错误。这在以前是不允许的,但在 Prisma ORM 4 之前被静默地接受了。你需要检查你的数据并将这些字段更改为null
。 -
如果你在 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
包都使用脱字符 ^
在它们的版本号中安装。这允许升级到新的次要版本,但不允许升级到主要版本,以防范重大变更。
要忽略脱字符 ^
并跨主要版本升级,你可以在使用 npm
或 yarn
升级时使用 @4
标签
在你升级之前,请检查每个 **重大变更** 以查看升级可能如何影响你的应用程序。
- npm
- yarn
npm install prisma@4 @prisma/client@4
yarn up prisma@4 @prisma/client@4
视频指南
有关升级过程的视频演示和升级场景示例,请观看我们关于升级到 Prisma ORM 4 的录制直播