Prisma ORM は ORM ですか?
質問に手短に答えると、はい、Prisma ORM は新しい種類の ORM であり、従来の ORM と根本的に異なり、従来の ORM によく関連付けられる多くの問題に悩まされることはありません。
従来の ORM は、リレーショナルデータベースを操作するためのオブジェクト指向の方法を提供し、テーブルをプログラミング言語のモデルクラスにマッピングします。このアプローチは、オブジェクト・リレーショナル・インピーダンス・ミスマッチによって引き起こされる多くの問題につながります。
Prisma ORM は、それとは根本的に異なる方法で動作します。Prisma ORM では、宣言的なPrisma スキーマでモデルを定義します。これは、データベーススキーマとプログラミング言語のモデルの単一の信頼できる情報源として機能します。アプリケーションコードでは、Prisma Client を使用して、複雑なモデルインスタンスを管理するオーバーヘッドなしに、型安全な方法でデータベース内のデータを読み書きできます。これにより、Prisma Client は常にプレーンな JavaScript オブジェクトを返すため、データのクエリプロセスがより自然になり、予測可能性も高まります。
この記事では、ORM パターンとワークフロー、Prisma ORM がデータマッパーパターンをどのように実装しているか、および Prisma ORM のアプローチの利点について詳しく学びます。
ORM とは何ですか?
すでに ORM に精通している場合は、Prisma ORM に関する次のセクションまでスキップしてください。
ORM パターン - アクティブレコードとデータマッパー
ORM は、高レベルのデータベース抽象化を提供します。オブジェクトを介してプログラムインターフェイスを公開し、データの作成、読み取り、削除、および操作を行いながら、データベースの複雑さの一部を隠蔽します。
ORM のアイデアは、モデルをデータベース内のテーブルにマッピングするクラスとして定義することです。クラスとそのインスタンスは、データベース内のデータを読み書きするためのプログラム API を提供します。
一般的な ORM パターンは 2 つあります。アクティブレコードとデータマッパーであり、オブジェクトとデータベース間でデータを転送する方法が異なります。どちらのパターンも、主要な構成要素としてクラスを定義する必要がありますが、2 つの最も顕著な違いは、データマッパーパターンがアプリケーションコード内のインメモリオブジェクトをデータベースから分離し、データマッパー層を使用して 2 つの間でデータを転送することです。実際には、これはデータマッパーを使用すると、インメモリオブジェクト(データベース内のデータを表す)は、データベースが存在することさえ認識していないことを意味します。
アクティブレコード
アクティブレコード ORM は、モデルクラスをデータベーステーブルにマッピングします。ここで、2 つの表現の構造は密接に関連しています。たとえば、モデルクラスの各フィールドには、データベーステーブル内の一致する列があります。モデルクラスのインスタンスは、データベース行をラップし、データベース内の変更の永続化を処理するためのデータとアクセスロジックの両方を持ち運びます。さらに、モデルクラスは、モデル内のデータに固有のビジネスロジックを持つことができます。
モデルクラスには通常、次の処理を行うメソッドがあります。
- SQL クエリからモデルのインスタンスを構築します。
- テーブルに後で挿入するための新しいインスタンスを構築します。
- 一般的に使用される SQL クエリをラップし、アクティブレコードオブジェクトを返します。
- データベースを更新し、アクティブレコード内のデータを挿入します。
- フィールドを取得および設定します。
- ビジネスロジックを実装します。
データマッパー
データマッパー ORM は、アクティブレコードとは対照的に、アプリケーションのインメモリデータ表現をデータベースの表現から分離します。分離は、マッピングの責任を 2 種類のクラスに分離する必要があることによって実現されます。
- エンティティクラス:データベースに関する知識を持たないエンティティのアプリケーションのインメモリ表現
- マッパークラス:これらには 2 つの責任があります。
- 2 つの表現間でデータを変換します。
- データベースからデータをフェッチし、データベース内の変更を永続化するために必要な SQL を生成します。
データマッパー ORM を使用すると、コードとデータベースに実装された問題領域の間でより柔軟性が高まります。これは、データマッパーパターンを使用すると、データベースが実装されている方法を隠蔽できるためです。これは、データマッピング層全体の背後にあるドメインについて考える理想的な方法ではありません。
従来のデータマッパー ORM がこれを行う理由の 1 つは、2 つの責任が別々のチームによって処理される組織構造によるものです。たとえば、DBAとバックエンド開発者です。
実際には、すべてのデータマッパー ORM がこのパターンに厳密に従っているわけではありません。たとえば、TypeScript エコシステムで人気のある ORM であり、アクティブレコードとデータマッパーの両方をサポートするTypeORMは、データマッパーに対して次のアプローチを取ります。
- エンティティクラスは、デコレータ (
@Column
) を使用して、クラスプロパティをテーブル列にマッピングし、データベースを認識します。 - マッパークラスの代わりに、リポジトリクラスはデータベースのクエリに使用され、カスタムクエリを含めることができます。リポジトリはデコレータを使用して、エンティティプロパティとデータベース列間のマッピングを決定します。
データベースに次の User
テーブルがあるとします。
これは、対応するエンティティクラスがどのようになるかを示しています。
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column({ name: 'first_name' })
firstName: string
@Column({ name: 'last_name' })
lastName: string
@Column({ unique: true })
email: string
}
スキーマ移行ワークフロー
データベースを利用するアプリケーション開発の中心的な部分は、新しい機能に対応し、解決しようとしている問題により適合するようにデータベーススキーマを変更することです。このセクションでは、スキーマ移行とは何か、およびそれらがワークフローにどのように影響するかについて説明します。
ORM は開発者とデータベースの間に位置するため、ほとんどの ORM はデータベーススキーマの作成と変更を支援する移行ツールを提供します。
移行とは、データベーススキーマをある状態から別の状態にするための一連のステップです。最初の移行では、通常、テーブルとインデックスが作成されます。後続の移行では、列の追加または削除、新しいインデックスの導入、または新しいテーブルの作成を行う場合があります。移行ツールによっては、移行は SQL ステートメントまたはプログラムコードの形式になる場合があります。プログラムコードは SQL ステートメントに変換されます (ActiveRecordやSQLAlchemyの場合のように)。
データベースには通常データが含まれているため、移行はスキーマの変更を小さな単位に分解するのに役立ち、不注意によるデータ損失を防ぐのに役立ちます。
プロジェクトをゼロから開始すると仮定すると、これは完全なワークフローがどのようになるかを示しています。データベーススキーマに User
テーブルを作成する移行を作成し、上記の例のように User
エンティティクラスを定義します。
次に、プロジェクトが進行し、salutation
列を User
テーブルに追加したいと判断した場合は、テーブルを変更して salutation
列を追加する別の移行を作成します。
TypeORM の移行でそれがどのように見えるかを見てみましょう。
import { MigrationInterface, QueryRunner } from 'typeorm'
export class UserRefactoring1604448000 implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "User" ADD COLUMN "salutation" TEXT`)
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "User" DROP COLUMN "salutation"`)
}
}
移行が実行され、データベーススキーマが変更されたら、新しい salutation
列に対応するようにエンティティクラスとマッパークラスも更新する必要があります。
TypeORM では、これは salutation
プロパティを User
エンティティクラスに追加することを意味します。
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column({ name: 'first_name' })
firstName: string
@Column({ name: 'last_name' })
lastName: string
@Column({ unique: true })
email: string
@Column()
salutation: string
}
このような変更の同期は、変更が手動で適用され、プログラムで簡単に検証できないため、ORM では課題となる可能性があります。既存の列の名前を変更すると、さらに面倒になり、列への参照を検索して置換する必要があります。
注: Django の makemigrations CLI は、Prisma ORM と同様に、同期の問題を解消するモデルの変更を検査することで移行を生成します。
要約すると、スキーマを進化させることは、アプリケーション構築の重要な部分です。ORM を使用したスキーマ更新のワークフローには、移行ツールを使用して移行を作成し、対応するエンティティクラスとマッパークラス (実装によって異なります) を更新することが含まれます。ご覧のとおり、Prisma ORM はこれに対して異なるアプローチを取ります。
移行とは何か、およびそれらが開発ワークフローにどのように適合するかを理解したところで、ORM の利点と欠点について詳しく学びます。
ORM の利点
開発者が ORM を使用することを選択する理由はさまざまです。
- ORM は、ドメインモデルの実装を容易にします。ドメインモデルは、ビジネスロジックの動作とデータを組み込んだオブジェクトモデルです。言い換えれば、データベース構造や SQL セマンティクスではなく、実際のビジネス概念に集中できるようにします。
- ORM は、コード量を削減するのに役立ちます。一般的な CRUD (作成、読み取り、更新、削除) 操作のための反復的な SQL ステートメントの記述や、SQL インジェクションなどの脆弱性を防ぐためのユーザー入力のエスケープの手間を省きます。
- ORM を使用すると、(複雑さによっては、依然として奇妙な生のクエリを記述する必要がある場合がありますが) SQL をほとんどまたはまったく記述する必要がなくなります。これは、SQL に精通していないが、それでもデータベースを操作したい開発者にとって有益です。
- 多くの ORM は、データベース固有の詳細を抽象化します。理論的には、これは ORM を使用すると、あるデータベースから別のデータベースへの変更が容易になる可能性があることを意味します。実際には、アプリケーションが使用するデータベースを変更することはめったにないことに注意する必要があります。
生産性の向上を目的としたすべての抽象化と同様に、ORM を使用することには欠点もあります。
ORM の欠点
ORM の欠点は、使い始めたときは必ずしも明らかになるとは限りません。このセクションでは、一般的に受け入れられている欠点のいくつかについて説明します。
- ORM を使用すると、データベーステーブルのオブジェクトグラフ表現が形成され、オブジェクト・リレーショナル・インピーダンス・ミスマッチにつながる可能性があります。これは、解決しようとしている問題が複雑なオブジェクトグラフを形成し、リレーショナルデータベースに簡単にマッピングされない場合に発生します。リレーショナルデータベース内のデータ表現と、インメモリ (オブジェクトを使用) のデータ表現という、2 つの異なるデータ表現の間で同期をとることは非常に困難です。これは、オブジェクトがリレーショナルデータベースレコードと比較して、相互に関係する方法がより柔軟で多様であるためです。
- ORM は問題に関連する複雑さを処理しますが、同期の問題は解消されません。データベーススキーマまたはデータモデルへの変更には、変更を反対側にマッピングし直す必要があります。この負担は多くの場合、開発者にあります。プロジェクトに取り組むチームのコンテキストでは、データベーススキーマの変更には調整が必要です。
- ORM は、カプセル化する複雑さのために、大規模な API サーフェスを持つ傾向があります。SQL を記述する必要がないことの裏返しは、ORM の使い方を学ぶのに多くの時間を費やすことです。これはほとんどの抽象化に当てはまりますが、データベースの仕組みを理解していなければ、遅いクエリを改善することは困難になる可能性があります。
- SQL が提供する柔軟性のため、一部の複雑なクエリは ORM ではサポートされていません。この問題は、生の SQL クエリ機能によって軽減されます。この機能では、ORM に SQL ステートメント文字列を渡し、クエリが実行されます。
ORM のコストと利点について説明したので、Prisma ORM とは何か、およびそれがどのように適合するかをよりよく理解できます。
Prisma ORM
Prisma ORM は、アプリケーション開発者がデータベースを簡単に操作できるようにする次世代 ORM であり、次のツールを備えています。
- Prisma Client: アプリケーションで使用するための自動生成された型安全なデータベースクライアント。
- Prisma Migrate: 宣言的なデータモデリングおよび移行ツール。
- Prisma Studio: データベース内のデータを参照および管理するための最新の GUI。
注: Prisma Client は最も著名なツールであるため、単に Prisma と呼ぶことがよくあります。
これら 3 つのツールは、データベーススキーマ、アプリケーションのオブジェクトスキーマ、および 2 つ間のマッピングの単一の信頼できる情報源としてPrisma スキーマを使用します。これはユーザーによって定義され、Prisma ORM を構成する主な方法です。
Prisma ORM は、型安全性、豊富なオートコンプリート、およびリレーションを取得するための自然な API などの機能により、ソフトウェアの構築において生産性と自信を高めます。
次のセクションでは、Prisma ORM がデータマッパー ORM パターンをどのように実装しているかについて学びます。
Prisma ORM がデータマッパーパターンをどのように実装しているか
記事の前半で述べたように、データマッパーパターンは、データベースとアプリケーションが異なるチームによって所有されている組織とうまく連携します。
マネージドデータベースサービスと DevOps プラクティスを備えた最新のクラウド環境の台頭により、より多くのチームがクロスファンクショナルなアプローチを採用しています。これにより、チームはデータベースや運用上の懸念事項を含む完全な開発サイクルを所有します。
Prisma ORM は、DB スキーマとオブジェクトスキーマのタンデムでの進化を可能にすることで、そもそも逸脱の必要性を減らしながら、@map
属性を使用してアプリケーションとデータベースをある程度分離された状態に保つことができます。これは制限のように思えるかもしれませんが、ドメインモデルの進化 (オブジェクトスキーマを介して) が事後的にデータベースに課せられるのを防ぎます。
Prisma ORM のデータマッパーパターンの実装が従来のデータマッパー ORM と概念的にどのように異なるかを理解するために、それらの概念と構成要素の簡単な比較を次に示します。
概念 | 説明 | 従来の ORM の構成要素 | Prisma ORM の構成要素 | Prisma ORM における信頼できる情報源 |
---|---|---|---|---|
オブジェクトスキーマ | アプリケーションのインメモリデータ構造 | モデルクラス | 生成された TypeScript 型 | Prisma スキーマのモデル |
データマッパー | オブジェクトスキーマとデータベースの間で変換するコード | マッパークラス | Prisma Client で生成された関数 | Prisma スキーマの @map 属性 |
データベーススキーマ | データベース内のデータの構造 (テーブルや列など) | 手書きまたはプログラム API で記述された SQL | Prisma Migrate によって生成された SQL | Prisma スキーマ |
Prisma ORM は、データマッパーパターンと次の追加の利点に合わせて調整されています。
- Prisma スキーマに基づいて Prisma Client を生成することにより、クラスとマッピングロジックを定義するボイラープレートを削減します。
- アプリケーションオブジェクトとデータベーススキーマ間の同期の課題を解消します。
- データベース移行は、Prisma スキーマから派生しているため、第一級市民です。
Prisma ORM のアプローチの背後にある概念について説明したので、Prisma スキーマが実際にどのように機能するかを見ていきましょう。
Prisma スキーマ
Prisma のデータマッパーパターンの実装の中心となるのは、Prisma スキーマです。これは、次の責任を負う単一の信頼できる情報源です。
- Prisma がデータベースに接続する方法を構成します。
- Prisma Client (アプリケーションコードで使用するための型安全な ORM) を生成します。
- Prisma Migrate を使用してデータベーススキーマを作成および進化させます。
- アプリケーションオブジェクトとデータベース列間のマッピングを定義します。
Prisma ORM のモデルは、アクティブレコード ORM とはわずかに異なる意味を持ちます。Prisma ORM では、モデルは Prisma スキーマで、テーブル、リレーション、および Prisma Client のプロパティへの列間のマッピングを記述する抽象エンティティとして定義されます。
例として、ブログの Prisma スキーマを次に示します。
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Post {
id Int @id @default(autoincrement())
title String
content String? @map("post_content")
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
上記の例の内訳を次に示します。
datasource
ブロックは、データベースへの接続を定義します。generator
ブロックは、Prisma ORM に TypeScript および Node.js 用の Prisma Client を生成するように指示します。Post
モデルとUser
モデルは、データベーステーブルにマッピングされます。- 2 つのモデルには、各
User
が多数の関連するPost
を持つことができる1 対多のリレーションがあります。 - モデルの各フィールドには、型があります。たとえば、
id
の型はInt
です。 - フィールドには、フィールド属性を含めて次を定義できます。
@id
属性を持つ主キー。@unique
属性を持つユニークキー。@default
属性を持つデフォルト値。@map
属性を使用したテーブル列と Prisma Client フィールド間のマッピング。たとえば、content
フィールド (Prisma Client でアクセス可能) は、post_content
データベース列にマッピングされます。
User
/ Post
リレーションは、次の図で視覚化できます。
Prisma ORM レベルでは、User
/ Post
リレーションは次のもので構成されています。
@relation
属性によって参照されるスカラーauthorId
フィールド。このフィールドはデータベーステーブルに存在します。これは、Post と User を接続する外部キーです。- 2 つのリレーションフィールド:
author
とposts
は、データベーステーブルに存在しません。リレーションフィールドは、Prisma ORM レベルでのモデル間の接続を定義し、Prisma スキーマと生成された Prisma Client にのみ存在します。Prisma Client では、リレーションにアクセスするために使用されます。
Prisma スキーマの宣言的な性質は簡潔であり、データベーススキーマと Prisma Client での対応する表現を定義できます。
次のセクションでは、Prisma ORM でサポートされているワークフローについて学びます。
Prisma ORM ワークフロー
Prisma ORM を使用したワークフローは、従来の ORM とはわずかに異なります。Prisma ORM は、新しいアプリケーションをゼロから構築する場合、または段階的に採用する場合に使用できます。
- 新しいアプリケーション (グリーンフィールド): まだデータベーススキーマがないプロジェクトは、Prisma Migrate を使用してデータベーススキーマを作成できます。
- 既存のアプリケーション (ブラウンフィールド): すでにデータベーススキーマがあるプロジェクトは、Prisma ORM によってイントロスペクションして、Prisma スキーマと Prisma Client を生成できます。このユースケースは、既存の移行ツールで機能し、段階的な採用に役立ちます。移行ツールとして Prisma Migrate に切り替えることができます。ただし、これはオプションです。
どちらのワークフローでも、Prisma スキーマがメインの構成ファイルです。
既存のデータベースを持つプロジェクトでの段階的な採用のワークフロー
ブラウンフィールドプロジェクトには、通常、何らかのデータベース抽象化とスキーマがすでに存在します。Prisma ORM は、既存のデータベースをイントロスペクションして、既存のデータベーススキーマを反映する Prisma スキーマを取得し、Prisma Client を生成することで、このようなプロジェクトと統合できます。このワークフローは、すでに使用している可能性のある移行ツールおよび ORM と互換性があります。段階的に評価および採用することを希望する場合は、このアプローチを並行採用戦略の一部として使用できます。
このワークフローと互換性のあるセットアップの網羅的ではないリスト
- データベーススキーマを作成および変更するために
CREATE TABLE
およびALTER TABLE
を含むプレーンな SQL ファイルを使用するプロジェクト。 - db-migrateまたはUmzugのようなサードパーティ移行ライブラリを使用するプロジェクト。
- すでに ORM を使用しているプロジェクト。この場合、ORM を介したデータベースアクセスは変更されませんが、生成された Prisma Client は段階的に採用できます。
実際には、既存の DB をイントロスペクションして Prisma Client を生成するために必要な手順は次のとおりです。
datasource
(この場合は既存の DB) とgenerator
を定義するschema.prisma
を作成します。
datasource db {
provider = "postgresql"
url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma"
}
generator client {
provider = "prisma-client-js"
}
prisma db pull
を実行して、データベーススキーマから派生したモデルで Prisma スキーマを生成します。- (オプション)フィールドとモデルのマッピングを Prisma Client とデータベース間でカスタマイズします。
prisma generate
を実行します。
Prisma ORM は、node_modules
フォルダー内に Prisma Client を生成します。Prisma Client は、アプリケーションでインポートできます。より広範な使用ドキュメントについては、Prisma Client API ドキュメントを参照してください。
要約すると、Prisma Client は、並行採用戦略の一部として、既存のデータベースとツールを備えたプロジェクトに統合できます。新しいプロジェクトでは、次に詳述する別のワークフローを使用します。
新しいプロジェクトのワークフロー
Prisma ORM は、サポートするワークフローの点で ORM とは異なります。新しいデータベーススキーマを作成および変更するために必要な手順を詳しく見ていくと、Prisma Migrate を理解するのに役立ちます。
Prisma Migrate は、宣言的なデータモデリングと移行のための CLI です。ORM の一部として付属しているほとんどの移行ツールとは異なり、ある状態から別の状態に移行する操作ではなく、現在のスキーマを記述するだけで済みます。Prisma Migrate は操作を推測し、SQL を生成して移行を実行します。
この例では、上記のブログの例と同様の新しいデータベーススキーマを持つ新しいプロジェクトで Prisma ORM を使用する方法を示します。
- Prisma スキーマを作成します。
// schema.prisma
datasource db {
provider = "postgresql"
url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma"
}
generator client {
provider = "prisma-client-js"
}
model Post {
id Int @id @default(autoincrement())
title String
content String? @map("post_content")
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
prisma migrate
を実行して、移行の SQL を生成し、データベースに適用し、Prisma Client を生成します。
データベーススキーマへの今後の変更の場合
- Prisma スキーマに変更を適用します。たとえば、
registrationDate
フィールドをUser
モデルに追加します。 prisma migrate
を再度実行します。
最後のステップでは、Prisma スキーマにフィールドを追加し、Prisma Migrate を使用してデータベーススキーマを目的の状態に変換することで、宣言的移行がどのように機能するかを示します。移行が実行されると、Prisma Client が自動的に再生成され、更新されたスキーマが反映されます。
Prisma Migrate を使用したくないが、新しいプロジェクトで型安全な生成された Prisma Client を引き続き使用したい場合は、次のセクションを参照してください。
Prisma Migrate なしで新規プロジェクトの代替案
Prisma Migrate の代わりにサードパーティのマイグレーションツールを使用して、新規プロジェクトで Prisma Client を使用することが可能です。例えば、新規プロジェクトでは、Node.js マイグレーションフレームワークであるdb-migrate を使用してデータベーススキーマとマイグレーションを作成し、Prisma Client をクエリに使用することができます。本質的に、これは既存のデータベースを持つプロジェクトにおける段階的な導入のワークフローでカバーされています。
Prisma Client でのデータへのアクセス
ここまで、この記事では Prisma ORM の背後にある概念、データマッパーパターンの実装、およびサポートするワークフローについて説明しました。最後のセクションでは、Prisma Client を使用してアプリケーションでデータにアクセスする方法を見ていきます。
Prisma Client でのデータベースへのアクセスは、公開されているクエリメソッドを通じて行われます。すべてのクエリはプレーンな JavaScript オブジェクトを返します。上記のブログスキーマが与えられた場合、ユーザーのフェッチは次のようになります。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const user = await prisma.user.findUnique({
where: {
email: 'alice@prisma.io',
},
})
このクエリでは、findUnique()
メソッドは User
テーブルから単一の行をフェッチするために使用されます。デフォルトでは、Prisma ORM は User
テーブルのすべてのスカラーフィールドを返します。
注意: この例では、Prisma Client が提供する型安全機能 を最大限に活用するために TypeScript を使用しています。ただし、Prisma ORM は Node.js の JavaScript でも動作します。
Prisma Client は、Prisma スキーマからコードを生成することにより、クエリと結果を構造型 にマッピングします。これは、user
が生成された Prisma Client 内に関連付けられた型を持つことを意味します。
export type User = {
id: number
email: string
name: string | null
}
これにより、存在しないフィールドへのアクセスは型エラーを引き起こすことが保証されます。より広く言えば、すべてのクエリの結果の型はクエリを実行する前に既知であり、エラーの捕捉に役立ちます。たとえば、次のコードスニペットは型エラーを引き起こします。
console.log(user.lastName) // Property 'lastName' does not exist on type 'User'.
リレーションのフェッチ
Prisma Client でのリレーションのフェッチは、include
オプションを使用して行われます。たとえば、ユーザーとその投稿をフェッチするには、次のように行います。
const user = await prisma.user.findUnique({
where: {
email: 'alice@prisma.io',
},
include: {
posts: true,
},
})
このクエリでは、user
の型には Post
も含まれ、posts
配列フィールドでアクセスできます。
console.log(user.posts[0].title)
この例は、ドキュメントで詳細を学ぶことができるCRUD 操作のための Prisma Client の API の表面をなぞったにすぎません。主な考え方は、すべてのクエリと結果が型によってバックアップされており、リレーションのフェッチ方法を完全に制御できるということです。
結論
要約すると、Prisma ORM は、従来の ORM とは異なり、それらによく関連付けられる問題に悩まされない、新しい種類のデータマッパーORMです。
従来の ORM とは異なり、Prisma ORM では、Prisma スキーマ(データベーススキーマとアプリケーションモデルの宣言型単一ソース)を定義します。Prisma Client のすべてのクエリはプレーンな JavaScript オブジェクトを返すため、データベースとの対話プロセスがより自然で予測可能になります。
Prisma ORM は、新規プロジェクトを開始し、既存のプロジェクトに導入するための 2 つの主要なワークフローをサポートしています。どちらのワークフローでも、構成の主な手段は Prisma スキーマを介することです。
すべての抽象化と同様に、Prisma ORM と他の ORM はどちらも、データベースの基盤となる詳細の一部を異なる前提で隠蔽します。
これらの違いとユースケースはすべて、ワークフローと導入コストに影響を与えます。これらの違いを理解することで、情報に基づいた意思決定を行うのに役立つことを願っています。