跳到主要內容

升級到 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

  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 模型之間的一對一關係,您需要將 @unique 屬性新增到 profileId 欄位

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 將變更推送到您的 MongoDB 資料庫,或使用 prisma migrate dev 推送到 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 版本中,我們已將原始查詢型別對映普遍可用。在 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 版本開始,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 整數作為 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 版本開始,它們是物件。

有關更多資訊,請參閱按 null 值過濾

升級路徑
  1. 如果您使用字串字面量來處理這些值,則必須將其替換為以下命名常量:

    • DbNull: 替換為 Prisma.DbNull
    • JsonNull: 替換為 Prisma.JsonNull
    • AnyNull: 替換為 Prisma.AnyNull

    如果您已經使用這些命名常量,則無需採取任何操作。

  2. 如果您現在在將 Prisma.DbNull 作為 JSON 欄位的值傳遞時遇到型別錯誤,那麼這可能表明您的程式碼中存在一個 bug,而我們的型別在 4.0.0 版本之前並未捕獲到。您嘗試儲存 DbNull 的欄位在您的 schema 中可能不是可空的。因此,資料庫中儲存的是字面量 DbNull 字串而不是 NULL

  3. 在使用 Prisma.DbNullPrisma.JsonNullPrisma.AnyNull 與 MongoDB 配合使用時,您現在可能會遇到型別錯誤或執行時驗證錯誤。這以前從未有效,但在 Prisma ORM 4 之前被靜默接受。您需要審查您的資料並將這些欄位更改為 null

  4. 如果您在 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 包都以脫字元 ^ 安裝在其版本號中。這允許升級到新的次要版本,但不允許升級到主要版本,以防止破壞性變更。

要忽略脫字元 ^ 並跨主要版本升級,您可以在使用 npmyarn 升級時使用 @4 標籤

危險

在升級之前,請檢查每個**破壞性變更**,以瞭解升級可能如何影響您的應用程式。

npm install prisma@4 @prisma/client@4

影片指南

有關升級過程的影片演練和升級場景的示例,請參閱我們關於升級到 Prisma ORM 4 的錄製直播。

© . This site is unofficial and not affiliated with Prisma Data, Inc.