2026/03/23
Prisma
Node.js / TypeScript 向けの次世代 ORM(Object-Relational Mapper)
スキーマファイルを中心に型安全なデータアクセスを実現する設計
下記 Prisma を構成する主要な3つのコンポーネント
- Schema:データモデルとDB接続を定義するファイル(
schema.prisma) - Client:スキーマから自動生成される型安全なクエリビルダー
- Migrate:スキーマの変更をDBに反映するマイグレーションツール
PostgreSQL、MySQL / MariaDBなどに対応
導入方法
以下一例
# インストール
npm install prisma --save-dev
npm install @prisma/client
# 初期化(schema.prisma を生成)
npx prisma init --datasource-provider postgresql
# 生成されるファイル
.env ← DATABASE_URL を記載する
prisma/
schema.prisma ← スキーマ定義ファイル
schema.prisma
基本構成
// ジェネレーター設定(Prisma Client の生成設定)
generator client {
provider = "prisma-client-js"
}
// データソース設定(DB の接続情報)
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// モデル定義(テーブルの定義)
model User {
id Int @id @default(autoincrement())
email String @unique
role Role @default(USER)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email]) // インデックス
@@map("users") // テーブル名を指定(デフォルトは model 名)
}
// Enum定義
enum Role {
USER
ADMIN
MODERATOR
}
フィールド型一覧
| Prisma 型 | PostgreSQL | MySQL | 備考 |
|---|---|---|---|
String | text | varchar(191) | |
Int | integer | int | |
BigInt | bigint | bigint | |
Float | double precision | double | |
Decimal | decimal | decimal | |
Boolean | boolean | tinyint(1) | |
DateTime | timestamp | datetime | |
Json | jsonb | json | |
Bytes | bytea | longblob |
Prisma Client
下記のようにスキーマから生成
npx prisma generate
下記のように初期化
// PrismaClient はシングルトンで管理する(開発時の接続数爆発を防ぐ)
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', 'error', 'warn'] // 開発時はクエリログを出力
: ['error'],
})
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}
CRUD 操作
createMany,findUnique/findUniqueOrThrow,aggregate,upsertなど様々なメソッドが用意されている
トランザクション処理
$transaction API, Interactive transactions などが存在
マイグレーション運用
migrateコマンドでスキーマの変更を SQL ファイルとして管理する
変更履歴がprisma/migrations/配下にファイルとして残るため、Git で差分管理・レビュー可能
# 開発環境:スキーマ変更をマイグレーションファイルに反映する
npx prisma migrate dev --name add_user_role
# → prisma/migrations/20240315123456_add_user_role/migration.sql が生成される
# → Prisma Client が自動再生成される
# マイグレーションを適用
npx prisma migrate deploy
# マイグレーションの状態確認
npx prisma migrate status
# スキーマと DB の差分確認
npx prisma migrate diff \
--from-schema-datamodel prisma/schema.prisma \
--to-url $DATABASE_URL
# DB からスキーマを生成(既存 DB から Prisma を導入する場合)
npx prisma db pull
- https://www.prisma.io/docs/concepts/components/prisma-migrate
- https://www.prisma.io/docs/orm/reference/prisma-cli-reference
その他
Client 活用
スキーマから型を自動生成するだけでなく、モデルの型・クエリ引数の型を取り出して再利用できる
anyや手書きの型定義を避け、スキーマと型を一元管理
import { Prisma } from '@prisma/client'
// モデルの型を取得する
type User = Prisma.UserGetPayload<{}>
type UserWithPosts = Prisma.UserGetPayload<{
include: { posts: true }
}>
// select の結果に合わせた型を取得する
type UserSummary = Prisma.UserGetPayload<{
select: { id: true; name: true; email: true }
}>
// where 句の型
type UserWhere = Prisma.UserWhereInput
// 関数の引数型を Prisma の型で定義する
async function findUsers(where: Prisma.UserWhereInput): Promise<User[]> {
return prisma.user.findMany({ where })
}
- https://www.prisma.io/docs/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types
- https://www.prisma.io/docs/orm/reference/prisma-client-reference
Client Extensions 活用
$extendsを使うことでクエリに横断的な処理(ロギング・ソフトデリートなど)を追加できる
かつての$use(Middleware)の後継
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient().$extends({
// スロークエリログ
query: {
$allModels: {
async $allOperations({ model, operation, args, query }) {
const start = Date.now()
const result = await query(args)
const end = Date.now()
if (end - start > 100) {
console.warn(
`Slow query detected: ${model}.${operation} (${end - start}ms)`
)
}
return result
},
},
},
})
// ソフトデリート
const prismaWithSoftDelete = new PrismaClient().$extends({
query: {
post: {
async delete({ args, query: _ }) {
// delete を update(deletedAt のセット)に差し替える
return prisma.post.update({
where: args.where,
data: { deletedAt: new Date() },
})
},
async findMany({ args, query }) {
// deletedAt が null のレコードのみ取得する
args.where = {
...args.where,
deletedAt: null,
}
return query(args)
},
},
},
})
複数の拡張を組み合わせる場合は$extendsをチェーンする
各拡張を関数として分離しておくと再利用・テストがしやすくなる
const prisma = new PrismaClient()
.$extends(slowQueryExtension)
.$extends(softDeleteExtension)
接続設定
参考
- Prisma 公式ドキュメント:https://www.prisma.io/docs