prisma の使い方

Prisma is an open-source database toolkit. It includes a JavaScript/TypeScript ORM for Node.js, migrations and a modern GUI to view and edit the data in your database. You can use Prisma in new projects or add it to an existing one.

v7.6.09.3M/週Apache-2.0ORM / DB
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

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 generatePrisma Clientの再生成
npx prisma db pushスキーマをDBに直接反映(プロトタイピング向け)
npx prisma db pull既存DBからスキーマを逆生成
npx prisma studioデータ閲覧・編集用GUIを起動
npx prisma validateスキーマファイルの構文チェック
npx prisma formatスキーマファイルのフォーマット

類似パッケージとの比較

特徴PrismaTypeORMDrizzle ORMKnex.js
型安全性◎(スキーマから自動生成)○(デコレータベース)◎(スキーマから推論)△(手動で型定義)
マイグレーション内蔵内蔵内蔵内蔵
クエリスタイル独自APIActive Record / Data MapperSQLライククエリビルダ
生SQLサポート$queryRawありありネイティブ
GUIPrisma 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はデフォルトでリレーションをロードしません。includeselect を明示的に指定してください。

// ❌ 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 pushmigrate 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です。

比較記事