Prismaを使った型安全なデータベース操作

## Prismaとは？
Node.jsやTypeScriptを使用したアプリケーション開発で、データベースとのやり取りを簡素化し、型安全なデータベース操作を実現するためのORMです。ざっくり分かりやすく言うと、SQLを書かなくてもデータベースとやり取りがでできるツールになります。

Node.js自体には、リレーショナルデータベースに対して直接アクセスするための標準的なライブラリや統一されたインターフェースが存在しないので、データベースとの通信はNode.jsで一貫した方法で行うわけではなく、各データベースごとに異なる方法を使う必要があります。

そこでORMを使うことで、データベース操作を統一的に行えるようになり、異なるデータベースに対しても同じコードやメソッドで操作ができるようになります。

## 基本的な使い方

Todoアプリを前提として、Prismaの基本的な使い方を説明します。

### 1. Prismaスキーマの作成
Prismaスキーマは、データベースモデル、データソース、Prisma Clientの設定などを定義するファイルです。これをもとに、Prismaはデータベースのテーブルを自動的に作成し、さらに型安全なクエリを実行するためのクライアントライブラリを生成します。

スキーマは3つの要素で構成されています。
**・データソース定義 (datasource)**
**・ジェネレーター定義 (generator)**
**・モデル定義 (model)**

#### データソース定義 (datasource)
datasourceブロックでは、Prismaがどのデータベースに接続するかを定義します。
```typescript
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
```
`provider`：どのデータベースを使用するかを指定します。この例ではPostgreSQLを使用しています。その他に、mysql、sqlite、sqlserverなども使用可能です。
`url`：データベースへの接続URLを指定します。.envファイルの環境変数から取得します。

#### ジェネレーター定義 (generator)
generatorブロックでは、Prismaが生成するコードやクライアントライブラリの設定を行います。

```typescript
generator client {
  provider = "prisma-client-js"
}
```
`provider`：クライアントライブラリを生成するために使用されるツールです。この例ではJavaScriptやTypeScriptで使用できるPrisma Clientを生成するように設定されています。
Prisma Clientは、型安全なクエリを実行するための自動生成されるライブラリです。これを使って、Node.jsからデータベース操作を行います。

#### モデル定義 (model)
modelブロックでは、データベースのテーブルに対応するデータモデルを定義します。Prismaでは、各モデルがデータベースのテーブルに対応し、フィールドが各カラムに対応します。
```typescript
model Task {
  id          Int      @id @default(autoincrement())  // 主キー
  title       String   // タスクのタイトル
  description String?  // タスクの詳細（任意）
  completed   Boolean  @default(false)  // タスクの完了状態
  createdAt   DateTime @default(now())  // 作成日時
  updatedAt   DateTime @updatedAt       // 更新日時
}
```
`@id`は、このフィールドが主キーであることを示します。
`@default(autoincrement())`は、新しいタスクが作成されるたびに、IDが自動で1ずつ増加することを意味します。
`@default(false)`は、タスクが新規作成された時点では未完了（false）となるようにデフォルト値を設定しています。
`@default(now())`は、新しいタスクが作成された際に自動的に現在の日時が入力されます。
`@updatedAt`は、このフィールドが自動的に更新されることを意味します。データが変更されるたびに、このフィールドは自動で現在の日時に更新されます。

上記をまとめて記載したものがprismaスキーマになります。
```typescript
datasource db {
  provider = "postgresql"  // 使用するデータベース（ここではPostgreSQL）
  url      = env("DATABASE_URL")  // 環境変数から接続URLを取得
}

generator client {
  provider = "prisma-client-js"  // Prisma Clientを生成
}

model Task {
  id          Int      @id @default(autoincrement())  // 主キー
  title       String   // タスクのタイトル
  description String?  // タスクの詳細（任意）
  completed   Boolean  @default(false)  // タスクの完了フラグ（デフォルトは未完了）
  createdAt   DateTime @default(now())  // 作成日時
  updatedAt   DateTime @updatedAt       // 更新日時（自動更新）
}
```

スキーマに基づいてデータベースにテーブルを作成します。次のコマンドでPrismaのマイグレーションを実行します。

```typescript
npx prisma migrate dev --name init
```
これにより、データベースにTaskテーブルが作成され、Prismaスキーマがデータベースに反映されます。

### 2.Prisma Clientの生成
Prisma Clientは、データベースとやり取りするためのクライアントライブラリです。以下のコマンドでPrisma Clientを生成します。

```typescript
npx prisma generate
```
これで、Node.jsからデータベース操作ができるようになります。

### 3.データ操作
次に、Prisma Clientを使って基本的なCRUD操作を行います。

**・タスクの作成**
```typescript
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

async function main() {
  // 新しいタスクを作成
  const newTask = await prisma.task.create({
    data: {
      title: 'Buy groceries',
      description: 'Milk, Bread, Eggs',
    },
  });
  console.log('Created new task:', newTask);
}

main()
  .catch((e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
```
`prisma.task.create`を使って、新しいタスクをデータベースに追加します。

**・タスクの一覧を取得**
```typescript
async function getTasks() {
  const tasks = await prisma.task.findMany();
  console.log('All tasks:', tasks);
}
```
`prisma.task.findMany`を使って、`Task`テーブル内のすべてのタスクを取得します。

**・特定のタスクを取得**
```typescript
async function getTaskById(id) {
  const task = await prisma.task.findUnique({
    where: { id: id },
  });
  console.log('Task with ID:', id, task);
}

getTaskById(1)  // IDが1のタスクを取得
```
`prisma.task.findUnique`で、特定のIDに対応するタスクを取得します。

**・タスクの更新**
```typescript
async function updateTask(id) {
  const updatedTask = await prisma.task.update({
    where: { id: id },
    data: { completed: true },
  });
  console.log('Updated task:', updatedTask);
}

updateTask(1)  // IDが1のタスクを完了状態に更新
```
`prisma.task.update`を使って、タスクの`completed`フラグを更新します。

**・タスクの削除**
```typescript
async function deleteTask(id) {
  const deletedTask = await prisma.task.delete({
    where: { id: id },
  });
  console.log('Deleted task:', deletedTask);
}

deleteTask(1)  // IDが1のタスクを削除
```
`prisma.task.delete`を使って、特定のタスクをデータベースから削除します。

## まとめ
・Prismaは、Node.jsやTypeScriptでリレーショナルデータベースを簡単に操作するためのORMで、SQLを書かずに型安全なデータベース操作が可能

・Prismaスキーマでデータベースのモデルを定義し、マイグレーションを実行して自動的にデータベースにテーブルを作成できる

・Prisma Clientを使って、データベースへのクエリを簡単に実行できる

・型安全なクエリや自動補完機能により、開発時にエラーを防ぎ、コーディング効率が向上する。

Prismaを使えば、データベース操作が直感的で簡単になり、Node.jsやTypeScriptでの開発がスムーズに進められます。