Prisma導入チュートリアル(Next.js編)
投稿日: 2024年12月15日
Next.jsに「Prisma」を導入するためのチュートリアルです。この投稿では、Prisma を用いたデータベースの設計から作成、初期データの投入、そしてデータの確認までの一連の流れを詳しく解説していきます。データベースには「SQLite」を使用します。
ShiftBの「Webアプリ開発コース」の第10章「NextJSのバックエンド開発演習(前半)」に対応しています。
前提として Next.js による基本的な開発環境は構築されているものとします。
まずは、Prisma の本体と、データベースに初期データ(Seed)を投入するために必要なライブラリをインストールします。VSCode のターミナルから、以下のコマンドを実行してください。
npm i -D prisma
npm i -D ts-node
Prisma を使用するための準備として「初期化」をしていきます。 この処理は、プロジェクトフォルダに Prisma をインストール後、初回のみ実行するものになります。
ターミナルから次のコマンドを実行してください。npm
ではなくnpx
であることに注意してください。--datasource-provider sqlite
のオプションにより、データベースとして SQLite(エスキューライト、スクライト)を用いることを指示しています。
npx prisma init --datasource-provider sqlite
コマンドを実行すると、プロジェクトフォルダの直下にprisma
というフォルダが作成され、そのなかにschema.prisma
というファイル が作成されます。また、環境変数を設定するための.env
というファイルがプロジェクトフォルダの直下に作成されます(既にファイルが存在する場合は、設定が追記がされます)。
環境変数の設定ファイル.env
の内容を確認してください。#
から開始する行はコメント なので編集・削除しても問題ありません。ファイルの最後のほうでDATABASE_URL
という環境変数に対して"file:./dev.db"
がセットされているはずです。
DATABASE_URL="file:./dev.db"
これは Prisma がデータベース接続に際して参照する環境変数で、この値によって Prisma はdev.db
という「SQLiteのデータベースファイル(まだ現時点では作成されていません)」に接続するようになります。
データベースを設計していきます。
具体的には、ブログアプリに必要な各種データ(投稿記事、カテゴリ)を保存するためのテーブルのスキーマ(構造・型・制約など)をschema.prisma
に定義していきます。prisma
フォルダに作成されたschema.prisma
を次のように書き換え、保存してください。
// このファイルを更新したら...
// 1. `npm run dev` や `npx prisma studio` を停止
// 2. dev.db を削除
// 3. npx prisma db push
// 4. npx prisma generate
// 5. npx prisma db seed
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// ブログ記事テーブル
model Post {
id Int @id @default(autoincrement())
title String
content String
thumbnailUrl String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
postCategories PostCategory[]
}
// カテゴリーテーブル
model Category {
id Int @id @default(autoincrement())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts PostCategory[]
}
// ブログ記事とカテゴリーを多対多で紐付ける中間テーブル
model PostCategory {
id Int @id @default(autoincrement())
postId Int
categoryId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
}
schema.prisma
を編集・保存したら、ターミナルから次のコマンドを実行してください。
npx prisma db push
このコマンドにより、schema.prisma
に基づき実際にデータベースが作成され(現在の設定の場合はdev.db
というファイルが新たに作成され)、そのデータベースのなかに3つのテーブルがつくられます。
さらに、次のコマンドを実行してください。これにより、データベースを操作するためのメソッド(関数)や、各テーブルに対応した型などが TypeScript プログラムのなかで利用できるようになります。
npx prisma generate
例えば、TypeScript プログラムでimport { Post } from "@prisma/client";
のようにインポートすれば、schema.prisma
で定義した投稿記事の「型」が参照できるようになります。
Prisma を使って作成されたデータベースの内容は「Prisma Studio」というツールを使ってブラウザから確認することができます。Prisma Studio は、VSCodeのターミナルから、次のコマンドで起動します。
npx prisma studio
ブラウザから http://localhost:5555/ にアクセスします。トップ画面にはテーブル一覧 (モデル一覧)が表示されます。いまは「投稿記事のテーブル」を確認したいので「Post」を選択します。
画面が切り替わり、下図のようにPostテーブルのカラム(列)の構成が確認できます。レコードの追加後は、その内容について確認・編集することもできます。
タブ横の「+」のボタンを押下すると他のテーブルの内容を確認することができます。「Add record」のボタンを押下すると、この画面からレコードを追加することもできます(いまは追加しないでください)。
Prisma Studio の画面から1件ずつ手作業でレコードを追加することも可能ですが、プログラムでデータを作成してデータベースに一括挿入することもできます。
prisma
フォルダのなかにseed.ts
というファイルを新規作成して
次のような、初期データを投入するためのプログラムを貼付けて保存してください。
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient(); // PrismaClientのインスタンス生成
const main = async () => {
// 各テーブルから既存の全レコードを削除
await prisma.postCategory?.deleteMany();
await prisma.post?.deleteMany();
await prisma.category?.deleteMany();
// カテゴリデータの作成 (テーブルに対するレコードの挿入)
const c1 = await prisma.category.create({ data: { name: "カテゴリ1" } });
const c2 = await prisma.category.create({ data: { name: "カテゴリ2" } });
const c3 = await prisma.category.create({ data: { name: "カテゴリ3" } });
// 投稿記事データの作成 (テーブルに対するレコードの挿入)
const p1 = await prisma.post.create({
data: {
title: "投稿1",
content: "投稿1の本文。<br/>投稿1の本文。投稿1の本文。",
thumbnailUrl: "https://placehold.jp/800x400.png",
postCategories: {
create: [{ categoryId: c1.id }, { categoryId: c2.id }],
},
},
});
const p2 = await prisma.post.create({
data: {
title: "投稿2",
content: "投稿2の本文。<br/>投稿2の本文。投稿2の本文。",
thumbnailUrl: "https://placehold.jp/800x400.png",
postCategories: {
create: [{ categoryId: c2.id }, { categoryId: c3.id }],
},
},
});
console.log(JSON.stringify(p1, null, 2));
console.log(JSON.stringify(p2, null, 2));
};
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
このプログラムは、Next.js(フレームワーク)からは完全に切り離された独立したプログラムになります。そのため、これを実行するためにはちょっと工夫が必要で、それを設定していきます。
プロジェクトフォルダ直下のpackage.json
を開き、次のように"prisma":
の項目を追加してください。
{
"name": "next-blog-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
~ 以下、省略 ~
以上の設定によりts-node --compiler-options {"module":"CommonJS"} prisma/seed.ts
という初期データ投入ための長いコマンドが、npx prisma db seed
という短いコマンドで実行できるようになります。
VSCodeのターミナルから以下のコマンドを実行して、初期データを投入してください。
npx prisma db seed
このコマンドを実行すれば、いつでもDBを初期状態に戻すことができます。開発中では非常に便利ですね(ただし本番環境ではうっかり実行しないように💦)。
Prisma Studio(npx prisma studio
で起動)から各テーブルのレコードを確認してください(必要に応じてブラウザの再読み込みをしてください)。seed.ts
の実行によって、次のようにレコードが追加されているはずです。
Prisma Studio では、レコードの編集をすることもできます。セルをダブルクリックして値を編集し、「Save」のボタンを押下して編集を確定、書き込みします。
テーブルにカラム(列)を追加したり、カラムの型や名前を変更するなどのスキーマに関わる変更はschema.prisma
の編集が必要になります。
schema.prisma
を変更したときは、以下の手続きが必要になります(これを実行するとすべてのレコードとテーブルが消えるので注意してください)。
npm run dev
やnpx prisma studio
を実行しているときは停止する。
prisma
フォルダのなかのdev.db
を削除する。
ターミナルから npx prisma db push
を実行する。
ターミナルからnpx prisma generate
を実行する。
この処理によって「型」の情報が更新されるので、それが確実に反映されるように念のため VSCode のコマンドパレットから>Developer: Reload Window
を実行することをお勧めします。
ターミナルからnpx prisma db seed
を実行する。
schema.prisma
の変更にあわせてseed.ts
の内容も変更してください。
なお、prisma migrate
というコマンドを使えば、既存のデータを保持したままスキーマの変更も可能 ですが、開発の初期段階(消えて困るようなデータがデータベースに格納されていない状態)では、上記の手続きの方が確実です。