Prisma+Next.js+Route HandlerでAPIを実装する
この記事について
Prismaで1:NとかM:Nとかのリレーションをどう実装するか。また、それらのAPI実装をNext.jsのRoute Handlerでどうするか、について書きます。
テーブル実装
記事にコメントとカテゴリがつく、みたいなやつです。記事とコメントは1:N、記事とカテゴリはM:Nという感じです
ER図

PrismaにおけるM:Nについて
Prismaでは、M:Nの実装について、明示的定義と暗黙的定義の2種類が存在します。
明示的定義は、中間テーブルをschema.prismaに実装する、暗黙的定義の場合は実装しない、というのが違いです。前者の場合、中間テーブルの実装が必要ですが、中間テーブルに関連性以外の情報を持たせることができます。後者の場合、実装は不要ですが、関連性以外の情報は持たせられません。ただ、どちらの場合も、中間テーブルはちゃんと作られます。
詳細:https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/many-to-many-relations
なお、今回のサンプル実装は暗黙的定義です
API実装
サンプル実装です。エラー処理とかバリデーションチェックは入れてません。あと、ややAIに任せた部分もあるので、そこは多めに見てください
Category API
これについては、特にいうことはないかなと。Articleとの紐付けは、Aricles APIの方で解説します
Comment API
Article:Commentで1:Nの関係になっていますので、POSTなどで、ArticleIDが必要になりますが、それ以外はCategory APIとあまりかわらないかなと
Articles API
CategoryとはM:N、Commentとは1:Nの関係です
GETで紐づくデータを全部取りたい時はincludeを使う
Articleに紐づくCategoryとCommentも取りたい場合はincludeを使いましょう。includeがないと
const result = await prisma.article.findMany({
include: {
categories: true,
comments: true
}
});
こんな感じで取得できます
curl -s GET http://localhost:3000/api/articles/2 | jq .
{
"id": 2,
"title": "新しいタイトル",
"content": "更新された本文です",
"createdAt": "2025-10-23T06:10:14.443Z",
"updatedAt": "2025-10-23T06:10:14.443Z",
"categories": [
{
"id": 1,
"category": "日常生活",
"createdAt": "2025-10-23T06:09:49.937Z",
"updatedAt": "2025-10-23T06:09:49.937Z"
},
{
"id": 2,
"category": "ソフトウェアエンジニアリング",
"createdAt": "2025-10-23T06:10:07.567Z",
"updatedAt": "2025-10-23T06:10:07.567Z"
}
],
"comments": [
{
"id": 1,
"comment": "はじめてのNext.js記事へのコメント",
"articleId": 2,
"createdAt": "2025-10-23T06:11:18.123Z",
"updatedAt": "2025-10-23T06:11:18.123Z"
},
{
"id": 2,
"comment": "はじめてのNext.js記事へのコメントのコメント",
"articleId": 2,
"createdAt": "2025-10-29T02:31:46.196Z",
"updatedAt": "2025-10-29T02:31:46.196Z"
}
]
}
関連テーブル更新時のconnect / set / disconnectの使い分け
例えば、Article登録時にCategoryも登録したい場合は、connectまたはsetを使います。この際、リクエストにどのCategoryを登録するかをidで指定します。
const result = await prisma.article.create({
data: {
title,
content,
categories: {
// リクエストで指定されたcategoryのidを紐づけている
connect: categoryIds.map((id: number) => ({ id })),
},
},
});
他にもsetとdiscconnectという似たような性質のものがありますが、以下のように使い分ければ良いかと思います。あくまで目安なので要件次第ではあります
| 処理の目的 | Prismaの操作 | よく使うHTTPメソッド |
|---|---|---|
| 新しい記事を作成し、既存カテゴリを紐付ける | connect |
POST |
| 記事にカテゴリを追加する(部分更新) | connect |
PATCH |
| 記事のカテゴリを完全に入れ替える | set |
PUT |
| 記事からカテゴリを外す | disconnect |
PATCH / PUT |
まとめ
Prisma + NextJS + Route HandlerでAPIを実装する記事があまりなかった気がしたので書いてみました。これを使うと、NextJSでフルスタックっぽく開発ができるのはいいですね。
参考サイト
NextJSとPrismaの公式サイトです。書いた内容はここに詳しく書かれています
Discussion