升級到 Prisma ORM 4
Prisma ORM 4 引入了多項破壞性變更,當您從早期 Prisma ORM 版本升級時會遇到。本指南解釋了此次升級可能如何影響您的應用程式,並提供了處理所有變更的說明。
破壞性變更
本節概述了 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 的新索引型別:Hash(在 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 中的驗證錯誤。 -
使用
prisma db push將變更推送到您的 MongoDB 資料庫,或使用prisma migrate dev推送到 MySQL 資料庫。
強制對一對一和一對多關係使用 @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 |
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 整數作為 INT8 傳送到 PostgreSQL。這可能與您只接受 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 版本開始,它們是物件。
有關更多資訊,請參閱按 null 值過濾。
升級路徑
-
如果您使用字串字面量來處理這些值,則必須將其替換為以下命名常量:
DbNull: 替換為Prisma.DbNullJsonNull: 替換為Prisma.JsonNullAnyNull: 替換為Prisma.AnyNull
如果您已經使用這些命名常量,則無需採取任何操作。
-
如果您現在在將
Prisma.DbNull作為 JSON 欄位的值傳遞時遇到型別錯誤,那麼這可能表明您的程式碼中存在一個 bug,而我們的型別在 4.0.0 版本之前並未捕獲到。您嘗試儲存DbNull的欄位在您的 schema 中可能不是可空的。因此,資料庫中儲存的是字面量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 是一個弱型別資料庫。如果您的 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 的錄製直播。