升级到 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
- 仔细浏览更改列表,检查您是否受到破坏性更改的影响。
- 查看 Prisma schema 验证错误(通过
npx prisma validate或通过 Prisma VS Code 扩展)。- 如果您没有验证错误,请继续执行步骤 3。
- 如果您有验证错误
- 尝试将验证错误映射到以下列表中的更改,以了解是哪种更改导致了无效的 Prisma schema,并阅读链接的升级说明。它只能来自
- 1:1 关系的显式唯一约束
- 移除对隐式多对多关系中使用
references的支持 - 为 MySQL 和 MongoDB 的一对一和一对多关系中的
references参数强制执行引用字段的唯一性 - 移除对
type别名的非文档支持 - 移除 SQLite URL 的
sqlite协议 - 更好的字符串字面量语法
- 尝试将验证错误映射到以下列表中的更改,以了解是哪种更改导致了无效的 Prisma schema,并阅读链接的升级说明。它只能来自
- 重复上述步骤,直到您的 Prisma schema 有效。
- 运行
npx prisma db pull以将 Prisma schema 升级到所有新功能(例如extendedIndexes)。 - 查看 Prisma schema 的更改并验证其有效性。
- 继续执行 Prisma Client 步骤。
升级您的 Prisma Client 使用
- 仔细浏览更改列表以了解您是否受到破坏性更改的影响。
- 如果是,请阅读详细的升级说明。
- 如果不是,请继续执行 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 的新索引类型:哈希(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 schema 中表示的任何配置。
有关更多详细信息,请参阅我们索引配置文档的从以前版本升级部分。
标量列表默认值
对于支持标量列表的数据库连接器(PostgreSQL、CockroachDB 和 MongoDB),Prisma ORM 4 引入了在 Prisma schema 中使用 @default 属性设置默认值的功能
- 关系型数据库
- 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 schema 中表示的任何默认值。
一对一关系的显式 @unique 约束
在 Prisma ORM 4 中使用一对一关系时,您需要显式地将 @unique 属性添加到关系标量字段。例如,对于 User 和 Profile 模型之间的一对一关系,您需要将 @unique 属性添加到 profileId 字段
- 关系型数据库
- 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 schema 中的验证错误。 -
对于 MongoDB 使用
prisma db push或对于 MySQL 使用prisma migrate dev将更改推送到您的数据库。
强制使用 @unique 或 @id 属性用于一对一和一对多关系(MySQL 和 MongoDB)
在 Prisma ORM 4 中使用一对一和一对多关系时,您需要在关系字段上使用 @unique 属性,以保证关系的单数侧只有一条记录。这现在对 MySQL 和 MongoDB 强制执行,使它们与其他连接器保持一致。缺少 @unique 属性现在将触发验证错误。
在 User 和 Post 模型之间的一对多关系的以下示例中,必须将 @unique 属性添加到 email 字段
- 关系型数据库
- 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 模型之间的一对一关系的以下示例中,必须将 @unique 属性添加到 email 字段
- 关系型数据库
- 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 schema 中的验证错误。或者,如果您有一个最新的实时数据库,运行
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 schema 中的验证错误。或者,如果您有一个最新的实时数据库,运行
npx prisma db pull将自动移除references参数。
更好的字符串字面量语法
Prisma Schema 中的字符串字面量现在需要遵循与 JSON 中字符串相同的规则。这主要改变了一些特殊字符的转义。更多详细信息可以在JSON 规范或 JSON 网站上找到。
升级路径
这对于一些现有的 schema 来说是一个破坏性更改。升级到 Prisma ORM 4 后,不正确转义的字符将触发验证错误。要升级,您需要
- 按照这些说明升级到新的 Prisma ORM 4 包
- 手动修复 Prisma schema 中的验证错误。
Client 更改
本节包括影响 Prisma Client 的更改。
原始查询类型映射:标量值现在被反序列化为正确的 JavaScript 类型
在 3.14.x 和 3.15.x 版本中,原始查询类型映射通过预览功能 improvedQueryRaw 提供。在 4.0.0 版本中,我们已将原始查询类型映射普遍可用。在 4.0.0 及更高版本中,您无需使用 improvedQueryRaw 即可获得此功能。
原始查询现在将标量值反序列化为对应的 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 版本开始,queryRaw 或 queryRawUnsafe 返回的一些数据类型有所不同,如下所示
| 数据类型 | 4.0.0 版本之前 | 4.0.0 版本之后 |
|---|---|---|
DateTime | 作为 String 返回 | 作为 Date 返回 |
数字 | 作为 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.DbNullJsonNull:替换为Prisma.JsonNullAnyNull:替换为Prisma.AnyNull
如果您已经使用这些命名常量,则无需采取任何措施。
-
如果您现在在将
Prisma.DbNull作为 JSON 字段的值传递时遇到类型错误,这可能表明您的代码中存在一个错误,我们的类型在 4.0.0 版本之前没有捕获到。您尝试存储DbNull的字段可能在您的 schema 中不可为空。结果是,一个字面量DbNull字符串被存储在数据库中,而不是NULL。 -
现在,当您将
Prisma.DbNull、Prisma.JsonNull或Prisma.AnyNull与 MongoDB 一起使用时,您可能会遇到类型错误或运行时验证错误。这从未有效,但在 Prisma ORM 4 之前被默默接受。您需要检查您的数据并将这些字段更改为null。 -
如果您将动态 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。
- 您可以使用
@prisma/internals中的getDmmf()访问 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 的直播