lelelemon’s blog

カメの歩みでのんびり学んでいます。

【React】PrismaでDB検索/登録/更新/削除を行うー削除処理

はじめに

前回、 Prisma で検索処理のサンプルを書かせていただきましたが、今回は削除処理のサンプルになります。

lelelemon.hatenablog.com

 

DB定義再掲

schema.prisma
schema.prisma
generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model user { id Int @id @default(autoincrement()) nickname String @db.VarChar(255) created_at DateTime @default(now()) habbits habbit[] } model habbit { id Int @id @default(autoincrement()) user_id Int title String @db.VarChar(255) created_at DateTime @default(now()) updated_at DateTime? deleted_at DateTime? user user @relation(fields: [user_id], references: [id]) habbit_activities habbit_activity[] } model habbit_activity { id Int @id @default(autoincrement()) habbit_id Int checked Boolean created_at DateTime @default(now()) habbit habbit @relation(fields: [habbit_id], references: [id]) }

 

Prismaでレコード削除処理

早速、削除処理を実装していきます。

 

1レコード削除

habbit.ts
export async function deleteHabbitActivity(id: number) {
  return await prisma.habbit_activity.delete({
    where: {
      id,
    },
  });
}
  • SQL の 「WHERE 条件=A」 のように、削除したいレコードの対象のカラムと値を where パラメーターに指定する形で記載できます

 

複数レコード削除

habbit.ts
export async function deleteHabbitActivities(ids: number[]) {
  return await prisma.habbit_activity.deleteMany({
    where: {
      id: {
        in: ids,
      },
    },
  });
}
  • 複数レコードを削除する場合は、deleteMany メソッドを使用します
  • カラムのパラメーターにネストする形でさらに条件を指定することができます(上記例では IN 句を使用しています)
  • 他にも SQL の like 句にあたる contains など様々なパラメーターが使用できるので、下記も合わせてご参照ください

www.prisma.io

 

 

全レコード削除

habbit.ts
export async function deleteAllHabbitActivity() {
  return await prisma.habbit_activity.deleteMany({});
}
  • 全レコード削除の場合はシンプルに、deleteMany メソッドに対して「{}」を渡すことで無条件に全てのレコードが削除されます

 

カスケードデリート

habbit.ts
export async function deleteHabbit(id: number) {
  const deletedHabbitActivities = prisma.habbit_activity.deleteMany({
    where: {
      habbit_id: id,
    },
  });

  const deletedHabbit = prisma.habbit.delete({
    where: {
      id,
    },
  });

  return await prisma.$transaction([deletedHabbitActivities, deletedHabbit]);
}
  • 今回の例だと、habbitテーブルとhabbit_activityテーブルが1対多の関係で、habbitにhabbit_activityが紐づくような関係性となっており、
  • habbitテーブルのレコードを削除したら、紐づくhabbit_activityテーブルのレコードもまとめて削除します
  • habbit テーブルに対して、Prisma Client から delete メソッドを発行するだけではエラーになるので、以下に紹介されているように、
  • habbit_activity, habbit テーブルそれぞれに対する delete クエリー実行をまとめて $transaction メソッドに渡すことでカスケードデリートを行うような実装になります

www.prisma.io

 

動作確認

上記の削除処理を動作確認します。

 

検証コード

今回もNextJS の App Router の機能を使って、

src/app/api/habbit_activity/route.ts, src/app/api/habbit/route.ts に API を用意し、API リクエストでDB更新を検証します。

 

src/app/api/habbit_activity/route.ts
export async function DELETE(request: NextRequest) {
  try {
    const jsonBody = await request.json();
    const habbit_activity_ids = jsonBody.ids;
    if (!habbit_activity_ids) {
      return NextResponse.json({ message: "No IDs provided" }, { status: 400 });
    }

    switch (habbit_activity_ids.length) {
      case 0:
        const deletedHabbitAllActivity = await deleteAllHabbitActivity();
        return NextResponse.json(
          { message: "Success", data: deletedHabbitAllActivity },
          { status: 200 }
        );
      case 1:
        const deletedHabbitActivity = await deleteHabbitActivity(
          habbit_activity_ids[0]
        );
        return NextResponse.json(
          { message: "Success", data: deletedHabbitActivity },
          { status: 200 }
        );
      default:
        const deletedHabbitActivities = await deleteHabbitActivities(
          habbit_activity_ids
        );
        return NextResponse.json(
          { message: "Success", data: deletedHabbitActivities },
          { status: 200 }
        );
    }
  } catch (error) {
    console.error(`[Delete HabbitActivity]unexpected error: ${error}`);
    return NextResponse.json({ message: "Error" }, { status: 500 });
  }
}

 

src/app/api/habbit/route.ts
export async function DELETE(request: NextRequest) {
  try {
    const jsonBody = await request.json();
    // delete habbit
    const data = await deleteHabbit(jsonBody.id);
    return NextResponse.json({ message: "Success", data }, { status: 200 });
  } catch (error) {
    console.error(`[Delete Habbit]unexpected error: ${error}`);
    return NextResponse.json({ message: "Error" }, { status: 500 });
  }
}

 

1レコード削除

実行前テーブル状態

 

curl コマンドで削除実行

curl --location --request DELETE 'http://localhost:3000/api/habbit_activity' \
--header 'Content-Type: text/plain' \
--data '{
    "ids": [2]
}'

 

実行後テーブル状態

  • id:2 のレコードが削除されていることを確認できました

 

複数レコード削除

実行前テーブル状態

 

curl コマンドで削除実行

curl --location --request DELETE 'http://localhost:3000/api/habbit_activity' \
--header 'Content-Type: text/plain' \
--data '{
    "ids": [3,4]
}'

 

実行後テーブル状態

  • リクエストボディーで指定した 3,4 のレコードが削除されています

 

全レコード削除

実行前テーブル状態

 

curl コマンドで削除実行

curl --location --request DELETE 'http://localhost:3000/api/habbit_activity' \
--header 'Content-Type: text/plain' \
--data '{
    "ids": []
}'

 

実行後テーブル状態

  • 全てのレコードが削除されていることを確認できました

 

カスケードデリート

最後にカスケードデリートを試してみます。

habbit テーブルのレコードを削除すると、紐づくhabbit_activity テーブルのレコードも削除されることを確認していきます。

 

実行前テーブル状態

 

curl コマンドで削除実行

curl --location --request DELETE 'http://localhost:3000/api/habbit' \
--header 'Content-Type: text/plain' \
--data '{
    "id":3
}'

 

実行後テーブル状態

habbit テーブル

habbit_activity テーブル

  • habbit テーブルの id:3 のレコードと、紐づく habbit_activity テーブルのレコードが削除されていることを確認できました

 

 

終わりに

削除処理も更新処理などと同じように、where オプションとして条件を引き渡すことでシンプルに実装できることを知りました。

ここまで Prisma を使った CRUD を書かせていただきましたが、簡易なコードでDB操作を実現できることが知れて良かったです。

ここまでの内容が何かご参考になれば嬉しいです。

 

参考情報

www.prisma.io