Prisma の使い方 — Node.js/TypeScript向け次世代データベースORM
一言でいうと
Prismaは、TypeScriptファーストの次世代データベースORMです。スキーマ定義からクライアント生成、マイグレーション、データ閲覧GUIまでを一貫して提供し、型安全なデータベースアクセスを実現します。
どんな時に使う?
- TypeScript/Node.jsプロジェクトで型安全にDBアクセスしたい時 — スキーマから自動生成される型付きクライアントにより、クエリの記述ミスをコンパイル時に検出できます
- データベースマイグレーションを宣言的に管理したい時 — Prisma Schemaを変更するだけで差分マイグレーションSQLが自動生成されます
- 複数のデータベースを統一的なAPIで扱いたい時 — PostgreSQL、MySQL、SQLite、MongoDB、SQL Server、CockroachDBなどを同一のAPIで操作できます
インストール
# npm
npm install prisma --save-dev
npm install @prisma/client
# yarn
yarn add prisma --dev
yarn add @prisma/client
# pnpm
pnpm add prisma --save-dev
pnpm add @prisma/client
prisma はCLIツール(開発時依存)、@prisma/client はアプリケーションコードで使うランタイムクライアントです。
初期セットアップ:
npx prisma init
これにより prisma/schema.prisma と .env ファイルが生成されます。
基本的な使い方
1. スキーマ定義(prisma/schema.prisma)
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
}
2. マイグレーション実行
npx prisma migrate dev --name init
3. クライアント生成と利用
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
// ユーザーを作成
const user = await prisma.user.create({
data: {
email: "alice@example.com",
name: "Alice",
posts: {
create: {
title: "はじめての投稿",
content: "Prismaを使ってみました",
},
},
},
include: {
posts: true,
},
});
console.log(user);
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
このコードは完全に型安全です。user.posts の型は Post[] として推論され、存在しないフィールドを指定するとコンパイルエラーになります。
よく使うAPI
1. findUnique / findFirst — レコードの取得
// ユニークキーで1件取得
const user = await prisma.user.findUnique({
where: { email: "alice@example.com" },
});
// 条件に一致する最初の1件を取得
const firstPublished = await prisma.post.findFirst({
where: { published: true },
orderBy: { createdAt: "desc" },
});
2. findMany — 複数レコードの取得(フィルタ・ページネーション)
// 公開済み記事を新しい順に10件取得
const posts = await prisma.post.findMany({
where: {
published: true,
title: {
contains: "Prisma",
},
},
orderBy: { createdAt: "desc" },
skip: 0,
take: 10,
include: {
author: {
select: { name: true, email: true },
},
},
});
3. update / upsert — レコードの更新
// 更新
const updatedPost = await prisma.post.update({
where: { id: 1 },
data: { published: true },
});
// 存在すれば更新、なければ作成
const user = await prisma.user.upsert({
where: { email: "bob@example.com" },
update: { name: "Bob Updated" },
create: {
email: "bob@example.com",
name: "Bob",
},
});
4. delete / deleteMany — レコードの削除
// 1件削除
const deleted = await prisma.post.delete({
where: { id: 1 },
});
// 条件に一致するレコードを一括削除
const deletedCount = await prisma.post.deleteMany({
where: {
published: false,
createdAt: {
lt: new Date("2024-01-01"),
},
},
});
console.log(`${deletedCount.count}件削除しました`);
5. $transaction — トランザクション
// 複数操作をアトミックに実行
const [newUser, newPost] = await prisma.$transaction([
prisma.user.create({
data: { email: "carol@example.com", name: "Carol" },
}),
prisma.post.create({
data: {
title: "トランザクションテスト",
authorId: 1, // 既存ユーザーのID
},
}),
]);
// インタラクティブトランザクション(より柔軟な制御)
const result = await prisma.$transaction(async (tx) => {
const user = await tx.user.findUnique({
where: { email: "alice@example.com" },
});
if (!user) {
throw new Error("ユーザーが見つかりません");
}
const post = await tx.post.create({
data: {
title: "新しい記事",
authorId: user.id,
},
});
return post;
});
主要CLIコマンド
| コマンド | 説明 |
|---|---|
npx prisma init | プロジェクトの初期化 |
npx prisma migrate dev | 開発環境でマイグレーション実行 |
npx prisma migrate deploy | 本番環境でマイグレーション適用 |
npx prisma generate | Prisma Clientの再生成 |
npx prisma db push | スキーマをDBに直接反映(プロトタイピング向け) |
npx prisma db pull | 既存DBからスキーマを逆生成 |
npx prisma studio | データ閲覧・編集用GUIを起動 |
npx prisma validate | スキーマファイルの構文チェック |
npx prisma format | スキーマファイルのフォーマット |
類似パッケージとの比較
| 特徴 | Prisma | TypeORM | Drizzle ORM | Knex.js |
|---|---|---|---|---|
| 型安全性 | ◎(スキーマから自動生成) | ○(デコレータベース) | ◎(スキーマから推論) | △(手動で型定義) |
| マイグレーション | 内蔵 | 内蔵 | 内蔵 | 内蔵 |
| クエリスタイル | 独自API | Active Record / Data Mapper | SQLライク | クエリビルダ |
| 生SQLサポート | $queryRaw | あり | あり | ネイティブ |
| GUI | Prisma Studio内蔵 | なし | Drizzle Studio | なし |
| MongoDB対応 | ○ | ○ | ✕ | ✕ |
| 学習コスト | 中(独自スキーマ言語) | 高 | 低(SQLに近い) | 低 |
| パフォーマンス | 良好(Rustエンジン) | 普通 | 良好(軽量) | 良好 |
選定の目安:
- 型安全性とDX(開発体験)を最重視 → Prisma
- SQLに近い書き方で軽量に使いたい → Drizzle ORM
- 既存のActive Recordパターンに慣れている → TypeORM
- クエリビルダだけで十分 → Knex.js
注意点・Tips
PrismaClientはシングルトンで使う
開発環境でホットリロードを繰り返すと、接続が増え続ける問題があります。
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: process.env.NODE_ENV === "development" ? ["query"] : [],
});
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}
@prisma/client の再生成を忘れない
スキーマを変更したら npx prisma generate を実行してクライアントを再生成してください。prisma migrate dev 実行時には自動で再生成されますが、db push の場合は手動実行が必要なケースがあります。
N+1問題に注意
Prismaはデフォルトでリレーションをロードしません。include や select を明示的に指定してください。
// ❌ N+1が発生するパターン
const users = await prisma.user.findMany();
for (const user of users) {
const posts = await prisma.post.findMany({
where: { authorId: user.id },
});
}
// ✅ includeで一括取得
const users = await prisma.user.findMany({
include: { posts: true },
});
db push と migrate dev の使い分け
db push: プロトタイピングや初期開発向け。マイグレーション履歴を残さずスキーマを直接反映しますmigrate dev: チーム開発・本番運用向け。SQLマイグレーションファイルが生成され、バージョン管理できます
生SQLが必要な場合
// 型付き生SQL(Prisma 5.19+で改善)
const users = await prisma.$queryRaw<
{ id: number; email: string }[]
>`SELECT id, email FROM "User" WHERE email LIKE ${`%@example.com`}`;
環境変数の設定
.env ファイルに接続文字列を設定します。
# PostgreSQL
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
# MySQL
DATABASE_URL="mysql://user:password@localhost:3306/mydb"
# SQLite
DATABASE_URL="file:./dev.db"
注意: この記事はPrisma v7.x系を前提としています。v4以前とはAPI・CLIの挙動に差異がある場合があります。特にv5で導入されたクライアント拡張機能やv6以降の変更点については、公式ドキュメント(https://www.prisma.io/docs)を確認してください。
まとめ
Prismaは、スキーマ定義を起点に型安全なクライアント・マイグレーション・GUIを一貫して提供する、Node.js/TypeScript向けの強力なデータベースツールキットです。独自のスキーマ言語を学ぶ初期コストはありますが、一度導入すればクエリの型安全性と開発体験の向上を強く実感できます。チーム開発や中〜大規模プロジェクトで特にその真価を発揮するORMです。