Prisma ORM 4へのアップグレード
Prisma ORM 4では、以前のバージョンのPrisma ORMからアップグレードする際に、いくつかの**破壊的な変更**が導入されています。このガイドでは、このアップグレードがアプリケーションにどのように影響するかを説明し、変更に対処する方法の手順を示します。
破壊的な変更
このセクションでは、Prisma ORM 4における破壊的な変更の概要を説明します。これらの変更は、PrismaスキーマとPrisma Clientの両方に影響する一般的な変更、スキーマの変更、およびクライアントの変更に分類されています。
まずPrismaスキーマの検証エラーに対処し、次にデータベースをpullして新しいPrismaスキーマの機能を反映させ、最後にPrisma Clientの型エラーを修正し、テストスイートを実行して検証することを推奨します。
Prismaスキーマをアップグレードする
- 変更の一覧を注意深く確認し、破壊的な変更の影響を受けるかどうかを確認してください。
- Prismaスキーマの検証エラーを確認してください(
npx prisma validate
、またはPrisma VS Code拡張機能を使用)。- 検証エラーがない場合は、ステップ3に進んでください。
- 検証エラーがある場合
- 検証エラーを以下のリストの変更点にマッピングして、どの変更がPrismaスキーマを無効にしたのかを理解し、アップグレード方法に関するリンクされた手順をお読みください。以下のいずれかに起因する可能性があります。
- 1:1リレーションシップの明示的なユニーク制約
- 暗黙の多対多リレーションシップでの
references
の使用のサポートを削除 - MySQLおよびMongoDBの1対1および1対多リレーションシップにおける
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の新しいインデックスタイプ: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スキーマで表現されていなかった構成が失われる可能性があります。
詳細については、インデックス構成ドキュメントの「以前のバージョンからのアップグレード」セクションを参照してください。
スカラーリストのデフォルト
スカラーリストをサポートするデータベースコネクタ(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スキーマで表現されていなかったデフォルトが失われます。
1対1リレーションシップの明示的な@unique
制約
Prisma ORM 4で1対1リレーションシップを使用する場合、リレーションスカラーフィールドに@unique
属性を明示的に追加する必要があります。たとえば、UserモデルとProfileモデル間のこの1対1リレーションシップの場合、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
属性がない1対1リレーションシップは検証エラーをトリガーします。アップグレードするには、次の手順を実行する必要があります
-
これらの手順に従って、新しいPrisma ORM 4パッケージにアップグレードする
-
データモデルに明示的な
@unique
または@id
属性を追加して、Prismaスキーマの検証エラーを手動で修正します。 -
MongoDBの場合は
prisma db push
、MySQLの場合はprisma migrate dev
を使用して、変更をデータベースにプッシュします。
1対1および1対多リレーションシップでの@unique
または@id
属性の使用を強制(MySQLおよびMongoDB)
Prisma ORM 4で1対1および1対多リレーションシップを使用する場合、リレーションの単数側がレコードを1つしか持たないことを保証するために、リレーションフィールドに@unique
属性を使用する必要があります。これは現在、MySQLおよびMongoDBで強制されており、他のコネクタと一致するようになります。@unique
属性がない場合、検証エラーがトリガーされるようになります。
UserモデルとPostモデル間の1対多リレーションシップの次の例では、@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モデル間の1対1リレーションシップの次の例では、@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
属性がない1対1または1対多リレーションシップは検証エラーをトリガーします。アップグレードするには、次の手順を実行する必要があります
- これらの手順に従って、新しい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に影響する変更について説明します。
Rawクエリの型マッピング:スカラー値が正しいJavaScript型としてデシリアライズされるようになりました
バージョン3.14.xおよび3.15.xでは、rawクエリの型マッピングはプレビュー機能improvedQueryRaw
で使用可能でした。バージョン4.0.0では、rawクエリの型マッピングを一般公開しました。バージョン4.0.0以降でこの機能を使用するためにimprovedQueryRaw
を使用する必要はありません。
Rawクエリは、スカラー値を対応する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
に変換する必要があります。
上記の表の他のデータ型についても、同等のコード変更を行う必要があります。
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の整数をPostgreSQLにINT8
として送信します。これは、INT4
のみを入力として受け入れるユーザー定義関数と競合する可能性があります。
アップグレードパス
PostgreSQLデータベースで$queryRaw
またはパラメーター化された$queryRawUnsafe
クエリを使用する場合は、次のいずれかを実行してください
- ユーザー定義関数の整数の入力型を
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.DbNull
に置き換えるJsonNull
:Prisma.JsonNull
に置き換えるAnyNull
:Prisma.AnyNull
に置き換える
これらの名前付き定数をすでに使用している場合は、何もする必要はありません。
-
JSONフィールドの値として
Prisma.DbNull
を渡すと型エラーが発生する場合、これはおそらくバージョン4.0.0より前に型がキャッチしていなかったコードのバグを示しています。DbNullを保存しようとしたフィールドは、スキーマでnull許容ではない可能性があります。その結果、リテラルDbNull文字列がNULLの代わりにデータベースに保存されました。 -
MongoDBで
Prisma.DbNull
、Prisma.JsonNull
、またはPrisma.AnyNull
を使用すると、型エラーまたはランタイム検証エラーが発生する可能性があります。これは決して有効ではありませんでしたが、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はloosely-typedデータベースです。スキーマに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へのアップグレードに関する録画されたライブストリームをご覧ください