Next.jsとPrismaでデータベース操作#
Next.jsとPrismaでWebアプリケーションを作る4回目です。 最初からやりたい場合はナビゲーションから初回を開いてください。
ここでは、Next.jsアプリケーションでPrismaを使ってデータベースにデータを保存する方法を学びます。従来の構成ではTypeORMを使用していましたが、Next.jsプロジェクトではPrismaを使うのが一般的です。Prismaは型安全でモダンなORMツールで、Next.jsとの相性も抜群です。
データベースの準備#
まず、Podmanを使ってPostgreSQLデータベースを起動します。Podmanはこちらの手順でインストールしてください。
ターミナルでmynextappディレクトリに移動し、package.jsonに以下のスクリプトを追加します:
{
"name": "mynextapp",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"start:db": "podman run -d --rm -p 5432:5432 -v postgres:/var/lib/postgresql/data -e POSTGRES_PASSWORD=postgres --name postgres postgres:15-alpine"
},
// ...残りの設定
}
そして、ターミナルで以下のコマンドを実行してデータベースを起動します:
npm run start:db
Prismaのセットアップ#
次に、Prismaをインストールして初期化します:
npm install prisma @prisma/client
npx prisma init
このコマンドを実行すると、.env
ファイルとprisma
ディレクトリが作成されます。.env
ファイルを開いて以下のように編集してください:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
データモデルの定義#
prisma/schema.prisma
ファイルを開き、以下のようにアンケートのデータモデルを定義します:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Enquete {
id Int @id @default(autoincrement())
point Int
message String
mail String
}
定義したモデルでデータベースを初期化します:
npx prisma migrate dev --name init
このコマンドは、定義されたモデルに基づいてSQLマイグレーションファイルを生成し、それをデータベースに適用します。また、Prisma Clientも生成されます。
Prisma Clientの設定#
Prismaを使うためのクライアントを設定します。lib/prisma.ts
というファイルを作成して以下のように実装します:
import { PrismaClient } from '@prisma/client'
// PrismaClientのグローバルインスタンスを防ぐための対策
const globalForPrisma = global as unknown as { prisma: PrismaClient }
export const prisma = globalForPrisma.prisma || new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
このコードは、開発中に自動リロードが発生した際に複数のPrismaClientインスタンスが作成されることを防ぎます。
アンケート送信APIの作成#
Next.jsのAPI Routesを使ってアンケートを保存するAPIを作成します。app/api/enquetes/route.ts
というファイルを作成して以下のように実装します:
import { prisma } from '@/lib/prisma'
import { NextResponse } from 'next/server'
// アンケートデータの型定義
export interface EnqueteData {
point: number
message: string
mail: string
}
export async function POST(request: Request) {
try {
const body: EnqueteData = await request.json()
// バリデーション
if (!body.point || !body.message || !body.mail) {
return NextResponse.json(
{ error: '必須フィールドが不足しています' },
{ status: 400 }
)
}
// データベースに保存
const enquete = await prisma.enquete.create({
data: {
point: body.point,
message: body.message,
mail: body.mail
}
})
return NextResponse.json(enquete)
} catch (error) {
console.error('アンケート保存エラー:', error)
return NextResponse.json(
{ error: 'アンケートの保存に失敗しました' },
{ status: 500 }
)
}
}
// GETメソッドの実装(アンケート一覧取得用)
export async function GET() {
try {
const enquetes = await prisma.enquete.findMany()
return NextResponse.json(enquetes)
} catch (error) {
console.error('アンケート取得エラー:', error)
return NextResponse.json(
{ error: 'アンケートの取得に失敗しました' },
{ status: 500 }
)
}
}
このAPIは、POSTリクエストでアンケートデータを受け取って保存し、GETリクエストで保存されたアンケート一覧を返します。
アンケートIDでの個別取得API#
特定のアンケートを取得するためのAPIも作成します。app/api/enquetes/[id]/route.ts
というファイルを作成します:
import { prisma } from '@/lib/prisma'
import { NextResponse } from 'next/server'
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const id = parseInt(params.id)
if (isNaN(id)) {
return NextResponse.json(
{ error: '無効なIDです' },
{ status: 400 }
)
}
const enquete = await prisma.enquete.findUnique({
where: { id }
})
if (!enquete) {
return NextResponse.json(
{ error: 'アンケートが見つかりません' },
{ status: 404 }
)
}
return NextResponse.json(enquete)
} catch (error) {
console.error('アンケート取得エラー:', error)
return NextResponse.json(
{ error: 'アンケートの取得に失敗しました' },
{ status: 500 }
)
}
}
Prisma Studioでデータベースを視覚的に操作#
Prisma Studioは、データベースを視覚的に操作するためのWebインターフェースです。以下のコマンドで起動できます:
npx prisma studio
ブラウザが自動的に開き、http://localhost:5555 でPrisma Studioが表示されます。ここでデータベースのテーブルを確認したり、レコードを手動で追加・編集・削除したりできます。
Server Actionsでアンケートを保存#
API Routesだけでなく、Next.jsのServer Actionsを使ってアンケートを保存することもできます。app/actions/enquete.ts
というファイルを作成します:
'use server';
import { prisma } from '@/lib/prisma';
export async function saveEnquete(formData: FormData) {
try {
const point = parseInt(formData.get('point') as string);
const message = formData.get('message') as string;
const mail = formData.get('mail') as string;
// バリデーション
if (!point || !message || !mail) {
return {
success: false,
error: '必須フィールドが不足しています'
};
}
// データベースに保存
const enquete = await prisma.enquete.create({
data: {
point,
message,
mail
}
});
return {
success: true,
enquete
};
} catch (error) {
console.error('アンケート保存エラー:', error);
return {
success: false,
error: 'アンケートの保存に失敗しました'
};
}
}
このServer Actionは、HTMLフォームから直接呼び出すことができます。
まとめ#
Prismaを使うことで、TypeORMと比較して以下のような利点があります:
- 型安全性: PrismaはTypeScriptと緊密に統合されているため、より型安全なコードを書けます
- 自動生成されるクライアント: スキーマ定義から自動的にクライアントが生成されます
- Prisma Studio: データベースを視覚的に操作できるツールが組み込まれています
- マイグレーション: データベーススキーマの変更を簡単に追跡・適用できます
- Next.jsとの統合: Server ComponentsやServer Actionsとシームレスに連携できます
Next.jsとPrismaを組み合わせることで、フルスタックアプリケーションの開発が非常にシンプルかつ効率的になります。
次は、Next.jsでマルチページアプリケーションを作成する方法を学びましょう。