1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Prisma】Node.js / TypeScript / Express 環境での CRUD 処理実装

1
Last updated at Posted at 2025-11-18

はじめに

この記事では、Docker Compose で構築した Node.js / TypeScript / PostgreSQL 環境で、Prisma を使った CRUD 処理の実装手順について記載します。

開発環境

開発環境は以下の通りです。

  • Windows11
  • Docker Engine 27.0.3
  • Docker Compose 2
  • PostgreSQL 18.1
  • Node.js 24.11.0
  • npm 11.6.2
  • TypeScript 5.9.3
  • Express 5.1.0
  • Prisma 6.19.0

前提条件

以下が完了していることを前提とします。

  • Docker Compose 環境の構築
  • Prisma の初期化とマイグレーション実行
  • User テーブルの作成(id, email, name カラム)

詳細手順は以下の記事に記載があります。

Express のセットアップ

必要なパッケージのインストール

Express と関連パッケージをインストールします。

npm install express
npm install @types/express --save-dev

Express サーバーの基本実装

src/index.ts を以下のように書き換えます。

import express from "express";
import { PrismaClient } from "@prisma/client";

const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

// JSONリクエストボディをパースするミドルウェア
app.use(express.json());

// ヘルスチェック用エンドポイント
app.get("/", (req, res) => {
  res.json({ message: "Server is running" });
});

// サーバー起動
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

// アプリケーション終了時にPrisma接続をクリーンアップ
process.on("SIGINT", async () => {
  await prisma.$disconnect();
  process.exit(0);
});

動作確認

一度ここまでの実装の動作確認をします。

docker compose up --build

ブラウザまたは curl で http://localhost:3000 にアクセスして、レスポンスが返ることを確認します。

curl http://localhost:3000

以下のレスポンスが返ります。

{"message":"Server is running"}

CRUD 処理の実装

Create(作成)

ユーザーを新規作成するエンドポイントを実装します。

src/index.ts に以下のコードを追加します。

// ユーザー作成
app.post("/users", async (req, res) => {
  try {
    const { email, name } = req.body;

    // バリデーション
    if (!email || !name) {
      return res.status(400).json({ error: "Email and name are required" });
    }

    const user = await prisma.user.create({
      data: {
        email,
        name,
      },
    });

    res.status(201).json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to create user" });
  }
});

Read(読み取り)

ユーザー情報を取得するエンドポイントを実装します。

// 全ユーザー取得
app.get("/users", async (req, res) => {
  try {
    const users = await prisma.user.findMany();
    res.json(users);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to fetch users" });
  }
});

// 特定ユーザー取得
app.get("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const user = await prisma.user.findUnique({
      where: { id: Number(id) },
    });

    if (!user) {
      return res.status(404).json({ error: "User not found" });
    }

    res.json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to fetch user" });
  }
});

Update(更新)

ユーザー情報を更新するエンドポイントを実装します。

// ユーザー更新
app.put("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const { email, name } = req.body;

    const user = await prisma.user.update({
      where: { id: Number(id) },
      data: {
        ...(email && { email }),
        ...(name && { name }),
      },
    });

    res.json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to update user" });
  }
});

Delete(削除)

ユーザーを削除するエンドポイントを実装します。

// ユーザー削除
app.delete("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;

    await prisma.user.delete({
      where: { id: Number(id) },
    });

    res.status(204).send();
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to delete user" });
  }
});

完成したコード

src/index.ts の完成形は以下の通りです。

import express from "express";
import { PrismaClient } from "@prisma/client";

const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

app.use(express.json());

// ヘルスチェック
app.get("/", (req, res) => {
  res.json({ message: "Server is running" });
});

// ユーザー作成
app.post("/users", async (req, res) => {
  try {
    const { email, name } = req.body;

    if (!email || !name) {
      return res.status(400).json({ error: "Email and name are required" });
    }

    const user = await prisma.user.create({
      data: { email, name },
    });

    res.status(201).json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to create user" });
  }
});

// 全ユーザー取得
app.get("/users", async (req, res) => {
  try {
    const users = await prisma.user.findMany();
    res.json(users);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to fetch users" });
  }
});

// 特定ユーザー取得
app.get("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const user = await prisma.user.findUnique({
      where: { id: Number(id) },
    });

    if (!user) {
      return res.status(404).json({ error: "User not found" });
    }

    res.json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to fetch user" });
  }
});

// ユーザー更新
app.put("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const { email, name } = req.body;

    const user = await prisma.user.update({
      where: { id: Number(id) },
      data: {
        ...(email && { email }),
        ...(name && { name }),
      },
    });

    res.json(user);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to update user" });
  }
});

// ユーザー削除
app.delete("/users/:id", async (req, res) => {
  try {
    const { id } = req.params;

    await prisma.user.delete({
      where: { id: Number(id) },
    });

    res.status(204).send();
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to delete user" });
  }
});

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

process.on("SIGINT", async () => {
  await prisma.$disconnect();
  process.exit(0);
});

動作確認

コンテナを再起動して動作確認をします。

docker compose down
docker compose up --build

Create(ユーザー作成)

まず1人ユーザーを作成します。

image.png

もう1人ユーザーを作成します。

image.png

Read(ユーザー取得)

全ユーザーを取得します。

image.png

特定ユーザーを取得します。

image.png

Update(ユーザー更新)

name を更新します。

image.png

Delete(ユーザー削除)

ユーザーを削除すると、ステータスコード 204 No Content が返ります。

image.png

削除されたことを確認します。

image.png

コンテナ内からデータベースに接続して、データを直接確認することもできます。

docker compose exec db psql -U user -d sampledb

ユーザーテーブルの内容を確認します。

SELECT * FROM "User";

結果

 id |      email       |   name    
----+------------------+-----------
  2 | hoge@example.com | Hoge User
(1 row)

まとめ

Docker Compose 環境での Prisma を使った CRUD 処理の実装について説明しました。

ポイントは以下の通りです。

  • PrismaClient を使ってデータベース操作を実行
  • create でデータ作成、findMany / findUnique でデータ取得
  • update でデータ更新、delete でデータ削除
  • Express のルーティングと組み合わせた RESTful API の実装
  • エラーハンドリングとバリデーションの実装

Prisma の型安全な API により、TypeScript の恩恵を最大限に受けながら、安全かつ効率的にデータベース操作を行うことができます。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?