「自社システムのデータベース操作にSQL文を直接書くのは手間だし、ミスも怖い」「もっと安全で効率的にデータベースを扱えるツールはないか」――そんな課題を解決するのがPrisma ORMです。
本記事では、Prisma ORMの使い方を基礎から実践まで、環境構築・データベース設計・CRUD操作の具体的なコード例を交えて初心者にもわかりやすく解説します。
Prisma ORMとは?データベース操作を簡単にする仕組み
「Excelでの顧客管理が限界に来ている」「SaaSツールでは自社の業務フローに合わない」――こうした課題を解決するために自社専用のWebシステムを検討する際、避けて通れないのがデータベース操作です。
Prisma ORM(Object-Relational Mapping)は、データベース操作を直感的かつ安全に行えるツールです。従来のSQL文を直接書く方法と比べて、TypeScriptやJavaScriptのコードでデータベースを扱えるため、開発スピードが大幅に向上します。
この記事では、Prisma ORMの使い方を基礎から実践まで解説します。環境構築からデータベース設計、実際のCRUD操作まで、具体的なコード例を交えながら説明していきます。
ORMの役割とPrismaの特徴
ORMとは「Object-Relational Mapping」の略で、データベースのテーブルをプログラミング言語のオブジェクトとして扱える技術です。ORMの基本概念についてはORMとは?メリット・デメリット解説もご覧ください。
通常、データベース操作にはSQL文が必要ですが、ORMを使うとプログラミング言語の自然な書き方でデータベースを操作できます。
SQL文での記述:
SELECT * FROM customers WHERE id = 1;
Prisma ORMでの記述:
const customer = await prisma.customer.findUnique({
where: { id: 1 }
});
Prismaが選ばれる主な理由は以下の3点です。
1. 型安全性による開発の安心感
TypeScriptとの相性が抜群で、データベースのスキーマから自動的に型定義を生成します。存在しないカラム名を指定するとエディタ上で即座にエラー表示されるため、実行前にバグを発見できます。
2. 優れた開発者体験
直感的なAPI設計、強力な自動補完、充実したCLIツールにより、開発期間の短縮とコストの削減が実現できます。
3. Schema駆動開発による設計の明確化
一つのSchemaファイルでデータベース全体の構造を管理できるため、チーム開発やドキュメント管理が容易になります。
Prismaが向いているプロジェクト
Prisma ORMは以下のようなプロジェクトに適しています。
適しているケース:
- 中小規模のWebアプリケーション(顧客管理、案件管理、予約システムなど)
- TypeScript/Node.jsを使ったプロジェクト
- スタートアップや新規事業のスピード重視の開発
- 段階的な機能追加が想定されるシステム
向いていないケース:
- 超大規模システムで極限までパフォーマンスを追求する場合
- 既存の複雑なレガシーデータベースとの統合
Prismaの基本構成と必要な環境
3つの主要コンポーネント
Prismaは主に3つのコンポーネントで構成されています。
1. Prisma Client
アプリケーションコードからデータベースを操作するライブラリです。データの作成、取得、更新、削除(CRUD操作)をTypeScriptやJavaScriptで記述できます。
2. Prisma Migrate
データベースのスキーマ変更を管理するツールです。変更履歴が残るため、チーム開発での同期や本番環境への適用が安全に行えます。
3. Prisma Studio
ブラウザ上で動作するデータベース管理ツールです。npx prisma studioコマンドで起動し、テーブルのデータを表形式で確認・編集できます。
Prisma Schemaファイルの構造
Prisma Schemaはprisma/schema.prismaという名前で保存され、以下の3つの情報を記述します。
// データソース設定
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ジェネレーター設定
generator client {
provider = "prisma-client-js"
}
// データモデル定義
model Customer {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now())
orders Order[]
}
対応データベースと必要な環境
対応データベース:
- PostgreSQL: 高機能で本番環境に最適
- MySQL: 普及率が高くレンタルサーバーでも利用可能
- SQLite: 軽量で開発環境やプロトタイプに最適
必要な環境:
- Node.js(バージョン14.17以上)
- npm または yarn
- Visual Studio Code(推奨)
- TypeScript(推奨)
環境構築と初期設定の手順
プロジェクトの作成とPrismaのインストール
# プロジェクトディレクトリの作成
mkdir my-prisma-project
cd my-prisma-project
npm init -y
# TypeScriptのインストール
npm install typescript ts-node @types/node --save-dev
npx tsc --init
# Prismaのインストール
npm install prisma --save-dev
npm install @prisma/client
Prisma Schemaの作成
# Prismaの初期化(SQLiteを使用)
npx prisma init --datasource-provider sqlite
このコマンドで以下のファイルが生成されます:
- prisma/schema.prisma:スキーマファイル
- .env:環境変数ファイル
データベース接続の設定
.envファイルでデータベース接続情報を設定します。
# SQLiteの場合
DATABASE_URL="file:./dev.db"
# PostgreSQLの場合
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
重要: .envファイルは機密情報を含むため、.gitignoreに追加してGitにコミットしないようにしましょう。
Prisma Clientの生成
npx prisma generate
生成されたクライアントを使用する基本的なコード:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
console.log('Prisma Clientが正常に動作しています')
}
main()
.catch((e) => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})
データベース設計:Schemaでテーブルを定義する
モデル定義の基本
model Customer {
id Int @id @default(autoincrement())
name String
email String @unique
phone String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
各要素の説明:
- @id:主キー
- @default(autoincrement()):自動採番
- String?:NULL許可
- @unique:一意制約
- @updatedAt:更新時に自動更新
フィールドの型とオプション
主なデータ型:
- String:文字列
- Int:整数
- Float:浮動小数点数
- Boolean:真偽値
- DateTime:日時
- Json:JSON形式
実用的な例:
model Project {
id Int @id @default(autoincrement())
projectCode String @unique
name String
status String @default("draft")
startDate DateTime?
budget Int?
description String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
リレーションの定義
1対多のリレーション:
model Customer {
id Int @id @default(autoincrement())
name String
orders Order[]
}
model Order {
id Int @id @default(autoincrement())
amount Int
customerId Int
customer Customer @relation(fields: [customerId], references: [id])
}
多対多のリレーション:
model Project {
id Int @id @default(autoincrement())
name String
members ProjectMember[]
}
model Member {
id Int @id @default(autoincrement())
name String
projects ProjectMember[]
}
model ProjectMember {
id Int @id @default(autoincrement())
projectId Int
memberId Int
role String @default("member")
project Project @relation(fields: [projectId], references: [id])
member Member @relation(fields: [memberId], references: [id])
@@unique([projectId, memberId])
}
マイグレーションの実行
スキーマを定義したら、マイグレーションでデータベースに反映します。
# 開発環境でのマイグレーション
npx prisma migrate dev --name init
# 本番環境でのマイグレーション
npx prisma migrate deploy
Prisma Clientを使ったCRUD操作
データの作成(Create)
// 単一データの作成
const customer = await prisma.customer.create({
data: {
name: '山田太郎',
email: 'yamada@example.com',
phone: '090-1234-5678'
}
})
// 関連データも同時に作成
const customerWithOrder = await prisma.customer.create({
data: {
name: '佐藤花子',
email: 'sato@example.com',
orders: {
create: [
{ amount: 10000 },
{ amount: 5000 }
]
}
}
})
データの取得(Read)
// 単一データの取得
const customer = await prisma.customer.findUnique({
where: { id: 1 }
})
// 複数データの取得
const customers = await prisma.customer.findMany({
where: {
email: { contains: '@example.com' }
},
orderBy: { createdAt: 'desc' },
take: 10
})
// 関連データを含めて取得
const customerWithOrders = await prisma.customer.findUnique({
where: { id: 1 },
include: { orders: true }
})
データの更新(Update)
// 単一データの更新
const updated = await prisma.customer.update({
where: { id: 1 },
data: { phone: '090-9876-5432' }
})
// 複数データの更新
const updateMany = await prisma.customer.updateMany({
where: { email: { contains: '@example.com' } },
data: { status: 'verified' }
})
データの削除(Delete)
// 単一データの削除
const deleted = await prisma.customer.delete({
where: { id: 1 }
})
// 複数データの削除
const deleteMany = await prisma.customer.deleteMany({
where: { createdAt: { lt: new Date('2023-01-01') } }
})
実務で役立つ便利な機能
複雑な検索条件
const results = await prisma.customer.findMany({
where: {
AND: [
{ email: { contains: '@example.com' } },
{ createdAt: { gte: new Date('2024-01-01') } }
],
OR: [
{ name: { contains: '山田' } },
{ name: { contains: '佐藤' } }
]
},
orderBy: [
{ createdAt: 'desc' },
{ name: 'asc' }
]
})
トランザクション処理
await prisma.$transaction(async (prisma) => {
const order = await prisma.order.create({
data: { customerId: 1, amount: 10000 }
})
await prisma.customer.update({
where: { id: 1 },
data: { totalSpent: { increment: 10000 } }
})
})
よく使うCLIコマンド
# スキーマの検証
npx prisma validate
# Prisma Studioの起動
npx prisma studio
# データベースの初期化
npx prisma db push
# マイグレーションの状態確認
npx prisma migrate status
トラブルシューティングと注意点
初心者がつまずきやすいポイント
| 問題 | 原因 | 対処法 |
|---|---|---|
Cannot find module '@prisma/client' |
Prisma Clientが未生成 | npx prisma generateを実行 |
| スキーマの変更が反映されない | 生成コマンドを実行していない | 変更後に必ずgenerateを実行 |
| マイグレーションエラー | データベースとスキーマの不整合 | npx prisma migrate resetで初期化 |
チーム開発での注意点
- マイグレーションファイルは必ずGitにコミットする
.envファイルは.gitignoreに追加する- スキーマ変更時はチームメンバーに共有し、
prisma migrate devを実行してもらう
まとめ
Prisma ORMを使うことで、データベース操作が直感的かつ安全になり、開発スピードが大幅に向上します。型安全性により属人化を防ぎ、誰でも安心してシステムを扱える環境が整います。
中小企業が「Excelや既製品のSaaSでは限界がある」という段階で、自社にちょうどいい業務システムを構築する際には、Prisma ORMは非常に有力な選択肢となります。
次のステップとして:
- 実際のプロジェクトでCRUD操作を実装してみる
- リレーションを使った複雑なデータ構造を設計する
- Next.jsなどのフレームワークと組み合わせてWebアプリケーションを構築する(tRPCとの連携も効果的です)
Harmonic Societyでは、Prisma ORMを活用した業務システム開発をサポートしています。自社に最適な「ちょうどいい」システムづくりをお手伝いしますので、お気軽にご相談ください。