PrismaでDBを操作する
このページで学ぶこと
- Prisma とは何かがわかる
- Prisma スキーマを定義してDBにテーブルを作れる
- Prisma Client でデータを取得・作成できる
Prisma とは
Prisma は JavaScript/TypeScript 向けの ORM(Object-Relational Mapper) です。
SQLを直接書く代わりに、JavaScriptのコードでDBを操作できます。
Prisma (ORM) の利点(簡潔版)
- SQLを毎回手書きしなくてよいので、開発スピードが上がる
- 型付きで補完が効くため、カラム名のミスに気づきやすい
- スキーマ変更をマイグレーションとして管理しやすい
// ❌ 素のSQLだとこう書く
const result = await db.query('SELECT * FROM todos WHERE user_id = $1', [userId])
// ✅ Prismaだとこう書ける
const todos = await prisma.todo.findMany({
where: { userId: userId }
})セットアップ
ステップ1: Prisma をインストール
npm install prisma --save-dev
npm install @prisma/client @prisma/adapter-pg pg dotenv
npx prisma initprisma/schema.prisma と .env が作成されます。
Prisma 7 では、CLI が使う接続先を prisma.config.ts で管理するのが基本です。
プロジェクトルートに prisma.config.ts を作成しましょう。
// prisma.config.ts
import 'dotenv/config' // .env を読み込む
import { defineConfig, env } from 'prisma/config'
export default defineConfig({
schema: 'prisma/schema.prisma', // Prismaスキーマの場所
datasource: {
url: env('DATABASE_URL'), // CLIが使うDB接続文字列
},
})ステップ2: schema.prisma を編集する
前のページで設計した構造をPrismaスキーマとして書きます。
prisma/schema.prisma を開いて編集する。
// prisma/schema.prisma
generator client {
provider = "prisma-client"
output = "../generated/prisma" // Prisma Client の生成先(Prisma 7 では output が必須)
}
datasource db {
provider = "postgresql"
}
model User {
id Int @id @default(autoincrement()) // 主キーで自動採番(1, 2, 3...)される
name String
email String @unique // ユニーク制約(同じ値は入れられない)
todos Todo[] // 1対多のリレーション(Userは複数のTodoを持てる)
createdAt DateTime @default(now()) @map("created_at") // デフォルト値を現在時刻にする & カラム名は created_at にする
@@map("users") // テーブル名を "users" にする
}
model Todo {
id Int @id @default(autoincrement())
title String
completed Boolean @default(false)
userId Int @map("user_id")
user User @relation(fields: [userId], references: [id])
createdAt DateTime @default(now()) @map("created_at")
@@map("todos")
}ステップ3: DBにテーブルを作成する(マイグレーション)
npx prisma migrate dev --name init
npx prisma generateコマンドの意味は次のとおりです。
prisma migrate dev: 開発環境のDBにスキーマ変更を反映するprisma generate: Prisma Client を生成する(Prisma 7 では明示実行)--name init: この変更セット(マイグレーション)にinitという名前を付ける
✅ Your database is now in sync with your schema. と表示されれば成功です。
Supabase のダッシュボード(Table Editor)を開くと users と todos テーブルができているはずです。
マイグレーションとは?
スキーマの変更をDBに反映させることです。
migrate devは開発環境用で、スキーマを変更するたびに実行します。
Prisma 7 では、変更後にprisma generateも忘れず実行しましょう。
ステップ4: Prisma Client を初期化する
lib/prisma.js を作成する。
// lib/prisma.js
import { PrismaClient } from '../generated/prisma/client.js' // ESM では拡張子 .js まで書く
import { PrismaPg } from '@prisma/adapter-pg'
// 開発環境での重複インスタンス防止
const globalForPrisma = globalThis
// PostgreSQL用のアダプターを作る(Prisma 7 では adapter が必須)
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
})
// ?? は「左が null / undefined のときだけ右を使う」演算子
export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter })
// NODE_ENV は実行環境を表す環境変数(development / production など)
// 開発時だけ global に保持して、ホットリロード時の多重接続を防ぐ
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}以下のコマンドを実行して、Prisma Client を生成しましょう。
npx prisma generateスキーマを変更したら、
migrate devのあとにgenerateまでを1セットで実行するのが安全です。
Prisma Client の基本操作
データを取得する
import { prisma } from '../lib/prisma'
// 全件取得
const todos = await prisma.todo.findMany()
// 条件付き取得
const myTodos = await prisma.todo.findMany({
where: { userId: 1 } // この章では userId は Int で扱う
})
// 1件取得
const todo = await prisma.todo.findUnique({
where: { id: 1 }
})
// 関連データも一緒に取得(JOIN)
// JOIN = 複数テーブルを結合してまとめて取るイメージ
const user = await prisma.user.findUnique({
where: { id: 1 },
include: { todos: true } // userとそのtodosを取得
})データを作成する
const newTodo = await prisma.todo.create({
data: {
title: '牛乳を買う',
userId: 1,
}
})データを更新する
const updated = await prisma.todo.update({
where: { id: 1 },
data: { completed: true }
})データを削除する
await prisma.todo.delete({
where: { id: 1 }
})API Route と組み合わせる
app/api/todos/route.js をPrismaを使うように書き換えましょう。
// app/api/todos/route.js
import { NextResponse } from 'next/server'
import { prisma } from '../../../lib/prisma'
export async function GET() {
const todos = await prisma.todo.findMany({
orderBy: { createdAt: 'desc' } // 新しい順に並べる
})
return NextResponse.json(todos)
}
export async function POST(request) {
const body = await request.json()
if (!body.title) {
return NextResponse.json({ error: 'titleは必須です' }, { status: 400 })
}
const todo = await prisma.todo.create({
data: {
title: body.title,
userId: 1, // TODO: 認証後は実際のユーザーID(文字列のUUID)を使う
}
})
return NextResponse.json(todo, { status: 201 })
}確認しよう
-
npx prisma initでPrismaを初期化した -
prisma.config.tsを作成してDATABASE_URLを設定した -
schema.prismaにモデルを定義した -
npx prisma migrate devでテーブルを作成した -
npx prisma generateで Prisma Client を生成した - Supabaseダッシュボードでテーブルができていることを確認した
-
prisma.todo.findMany()でデータを取得できた
AIに聞いてみよう
「Prismaのスキーマを変更したとき、既存のデータを保ちながらマイグレーションするにはどうしますか?」