Node.js/TypeScript ORMのPrisma。
高機能なので理解することがたくさんあるので、はじめ方をまとめてみた。
既存のDBがすでにあって、あとからPrismaを導入するときのイメージ。
全体の流れ
Prismaを使った開発の流れはこんな感じ。
- 事前準備
- 開発時
- 本番
初期設定
prisma
コマンドはnpx
で実行できるので、それを使っていく
初期ファイルの生成
まずは初期化。実行するとスキーマファイルが生成される。
$ npx prisma init prisma/ └── schema.prisma
接続情報の設定
次に接続情報を設定する。
生成されたschema.prisma
は以下のような感じなので、
datasource db
のprovider
とurl
を自分の環境に合わせて設定する
generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = "mysql://<USER>:<PASSWORD>@<HOST>:<PORT>/<DATABASE>" }
ConnectionURLの書き方などについては以下。 ・Connection URLs (Reference) | Prisma Docs
既存DBのスキーマの取得
既存のDBにPrisma Migrateを導入するガイドは以下。
・Adding Prisma Migrate to an existing project | Prisma Docs
接続情報のDBからスキーマを自動生成できる。
以下を実行すると、schema.prisma
が更新されて、
スキーマ定義が追加される。
$ npx prisma db pull
初期状態のマイグレーションファイルを生成
初期状態のスキーマファイルを作成する。
実行すると、migrations
フォルダ配下にSQLファイルが作成される。
(すでにmigrationsフォルダがある場合は、移動や削除が必要。)
初期状態のマイグレーションファイルを作成するためには、
全データを削除するreset
を行う必要があるので注意。
$ npx prisma migrate dev --name initial-migration --create-only prisma/ ├── migrations │ ├── 20210101000000_initial_migration │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma
以下のコマンドで、作成したマイグレーションファイルを適用できる。
$ npx prisma migrate dev
どのマイグレーションファイルを適用するかどうかは、
reset
時に作成される_prisma_migrations
テーブルをみて判断しているよう。
スキーマファイルを変更後に、npx prisma migrate dev
を実行すると、
マイグレーションファイルを作成した上で、実行もしてくれる。
開発時
スキーマを変更する
Prismaでは独自の書き方でスキーマを定義する。サンプルはこんな感じ。
@id
などで制約などを設定する感じ。enumも使える。
// schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int } enum Role { USER ADMIN }
細かい書き方は以下のドキュメントを参照。
・Data model (Reference) | Prisma Docs
・Prisma schema API (Reference) | Prisma Docs
Prisma Clientを生成する
Prismaではnpx prisma generate
を実行して、
schema.prisma
のスキーマ情報に沿ったクライアントを生成する。
Userモデルの作成や取得はこんな感じ。
prisma
に.user
が追加されたり、型のサポートを受けれる。
// run inside `async` function import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() const newUser = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', }, }) const users = await prisma.user.findMany()
細かい書き方は以下のドキュメントを参照。
・Prisma Client (Reference) | Prisma Docs
・Prisma Client API (Reference) | Prisma Docs
デフォルトでは、バージョン管理対象外になるように、
./node_modules/.prisma/client
配下に配置される。
ただ、@prisma/client
がインストールされると、
prisma generate
が呼ばれる仕組みのため、以下をインストールしておけばOK
$ npm i -D prisma $ npm i @prisma/client
・Generating the client (Concepts) | Prisma Docs
マイグレーションファイルを生成せず、スキーマを同期する
npx prisma migrate dev
を実行すると、毎回スキーマファイルが作成されるので、
開発時など頻繁に変更するときには少しめんどくさい。
開発用のコマンドもあり、npx prisma db push
を使うと、
マイグレーションファイルを生成せず同期できる。
いろいろ試して、変更点が整理できたら、
マイグレーションファイルを作成するのがよい感じ。
本番環境
マイグレーション履歴を設定する
Prismaを既存のDBへ導入する際、初期状態のマイグレーションファイルなど、
特定のマイグレーションファイルを適用したくない場合がある。
マイグレーション履歴をあらかじめ設定しておくことで、
実行されないようにする仕組みが用意されている。
上の図の場合、以下のコマンドで、
20210426141759_initial-migration
を適用済みとして設定する。
$ prisma migrate resolve --applied 20210426141759-initial-migration
時系列は見ていないので、20210322091837-new-field/migration.sql
まで、
適用済みとしたい場合は、以下のように両方設定が必要。
$ prisma migrate resolve --applied 20210426141759-initial-migration $ prisma migrate resolve --applied 20210322091837-new-field
・Adding Prisma Migrate to an existing project | Prisma Docs
マイグレーションを実行する
本番環境へ適用されていないマイグレーションをすべて実行する。
$ npx prisma migrate deploy
もし、マイグレーションに失敗した場合は、
prisma migrate resolve --rolled-back
を使って履歴を戻し、修正後再度実行すればOK。
・Migration troubleshooting in production | Prisma Docs
小ネタ
複数のデータベースを利用できるようにする
schema.prisma
を複数用意すれば実現できるよう。
・Multiple Connections / Databases · Issue #2443 · prisma/prisma
prisma/ │── schema1.prisma └── schema2.prisma
クライアントの出力先がかぶってしまうので、
client.output
もそれぞれ設定が必要。
// schema1.prisma datasource db { provider = "postgres" url = env("DB1_URL") } generator client { provider = "prisma-client-js" output = "./generated/client1" }
// schema2.prisma datasource db { provider = "postgres" url = env("DB2_URL") } generator client { provider = "prisma-client-js" output = "./generated/client2" }
クライアントを生成するときは、スキーマを指定して実行する。
prisma generate --schema prisma/schema1.prisma prisma generate --schema prisma/schema2.prisma
利用するときは、各クライアントをインポートすればOK
import { PrismaClient as PrismaClient1 } from '../prisma/client1' import { PrismaClient as PrismaClient2 } from '../prisma/client2' const client1 = new PrismaClient1() const client2 = new PrismaClient2()
ただ、元のIssueがオープンであったり、関連するIssueもまだある感じ。
特に性能面(速度・メモリ使用量)などが課題のよう。
・Reuse query engine for multiple PrismaClient
instances · Issue #5050 · prisma/prisma
・Shared query-engine instances for integration testing · Issue #6707 · prisma/prisma
複数の.envファイルを扱う
以下のようにenv("DATABASE_URL")
を使って、
接続先情報を環境変数から利用できるが、
開発時/本番時など切り替えるのがめんどう。
// schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") }
公式ドキュメントでは、dotenv-cil
を使った方法が紹介されている。
・Using multiple .env files. | Prisma Docs
# .env.development DATABASE_URL="postgresql://prisma:prisma@localhost:5433/dev"
# .env.test DATABASE_URL="postgresql://prisma:prisma@localhost:5433/tests"
# グローバルでインストール $ npm install -g dotenv-cli # dotenvで.envファイルを指定して実行 $ dotenv -e .env.test -- npx prisma migrate dev --name postgres-init
以上!! 便利(´ω`)
SSSAPIではβ版ユーザを募集しています!!
GoogleスプレッドシートをサクッとAPI化するサービスを開発してます!
β期間中は最上位プランが無料なので、この機会にぜひぜひお試しください(´ω`)
■SSSAPI
https://sssapi.app