跳到主要內容

升級至 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. 對於 MongoDB,使用 prisma db push 將變更推送至您的資料庫;對於 MySQL,使用 prisma migrate dev

強制對一對一和一對多關係使用 @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 的變更。

Raw 查詢類型映射:純量值現在反序列化為其正確的 JavaScript 類型

在 3.14.x 和 3.15.x 版本中,raw 查詢類型映射透過預覽功能 improvedQueryRaw 提供。在 4.0.0 版本中,我們已將 raw 查詢類型映射全面推出。您不需要在 4.0.0 和更高版本中使用 improvedQueryRaw 即可獲得此功能。

Raw 查詢現在會將純量值反序列化為其對應的 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 版本開始
DateTimeString 傳回Date 傳回
NumericFloat 傳回Decimal 傳回
BytesString 傳回Buffer 傳回
Int64Integer 傳回BigInt 傳回

如果您使用 queryRawqueryRawUnsafe 傳回上述任何資料類型,則您必須變更您的程式碼以處理新的類型。

例如,如果您傳回 DateTime 資料,則您需要考慮以下事項

  • 您不再需要手動為傳回的資料實例化 DateTime 物件。
  • 如果您的程式碼目前使用傳回的 String 資料,則您現在需要將 DateTime 物件轉換為 String

您必須對上表中的其他資料類型進行等效的程式碼變更。

Raw 查詢映射:PostgreSQL 類型轉換

在 3.14.x 和 3.15.x 版本中,raw 查詢類型映射透過預覽功能 improvedQueryRaw 提供。在 4.0.0 版本中,我們已將 raw 查詢類型映射全面推出。您不需要在 4.0.0 和更高版本中使用 improvedQueryRaw 即可獲得此功能。

在 4.0.0 版本之前,許多 PostgreSQL 類型轉換不起作用。我們已收緊類型強制轉換規則,以便所有類型轉換現在都起作用。因此,某些隱式轉換現在會失敗。

升級路徑

我們建議您重新測試您對 $queryRaw 的使用,以確保您傳遞到 raw 查詢中的類型與 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);`

Raw 查詢映射:PostgreSQL 和 JavaScript 整數

在 3.14.x 和 3.15.x 版本中,raw 查詢類型映射透過預覽功能 improvedQueryRaw 提供。在 4.0.0 版本中,我們已將 raw 查詢類型映射全面推出。您不需要在 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 欄位的值傳遞時收到類型錯誤,則這可能表示您的程式碼中存在錯誤,而我們的類型在 4.0.0 版本之前未捕獲該錯誤。您嘗試儲存 DbNull 的欄位可能在您的 schema 中不可為 null。因此,字串文字 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。
  • 您可以使用來自 @prisma/internalsgetDmmf() 來存取 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 的錄製直播