Prisma入門 – Node.js開発者向けの最高のORM

[![Group180.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/1566c887-1b8a-46c4-859e-13b605091d14.png)](https://leapcell.io/)


**[Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)**

# Prisma Tutorial: A Practical Exercise Based on Koa and Postgresql
## 序文
Prismaは、次世代のORM（Object Relational Mapping）ツールと見なされており、TypeScriptをベースに開発されており、強力な型安全性を提供しています。この記事では、Koa.jsを使用してシンプルなWebサービスを構築し、MySQLデータベースと組み合わせて、Prismaを通じてデータの作成、読み取り、更新、削除（CRUD）操作を実装する方法を示します。

## Prismaの概要
Prismaは、次世代のORMツールと称されています。Prismaはオープンソースのデータベースツールチェーンプロジェクトであり、その機能は単なるORMだけにとどまりません。PostgreSQL、MySQL、MongoDB、SQL Server、SQLiteなど、複数のデータベースをサポートしています。この記事では、MySQLを例にして説明します。

Prismaを初めて使用する際、その手順は比較的煩雑で、大きく以下のステップに分けられます：
1. 依存関係をインストールする
2. Prismaプロジェクトを初期化する
3. Prisma Schemaを設計する（データベース情報とモデルを定義する）
4. データベースと同期する
5. Prisma Clientを生成する
6. Prisma Clientを使用してCRUD操作を完了する

次に、まず開発環境をセットアップし、その後Prismaを詳しく紹介します。

## 環境の初期化
### Koa Webサービスの構築
まず、プロジェクトディレクトリを作成し、依存関係をインストールします：
```bash
mkdir koa-prisma
cd koa-prisma
pnpm init

# Koaの依存関係をインストール
pnpm add koa @koa/router koa-bodyparser
```
このうち、`@koa/router`はルーティングミドルウェアで、ルーティング機能を統合するのに便利です；`koa-bodyparser`は、リクエストボディデータを解析し、`ctx.request.body`オブジェクトに格納するために使用されます。

次に、新しい`index.js`ファイルを作成し、シンプルなWebサービスを構築します：
```javascript
const Koa = require('koa')
const Router = require('@koa/router')
const bodyParser = require('koa-bodyparser')

const app = new Koa()

// ルータをインスタンス化し、共通のルートプレフィックスを/usersに設定
const router = new Router({
  prefix: '/users'
})

app.use(bodyParser())

// ユーザーリストを照会する
router.get('/', async ctx => {

})

// 単一のユーザーを照会する
router.get('/:id', async ctx => {

})

// ユーザーを作成する
router.post('/', async ctx => {

})

// ユーザーを更新する
router.patch('/:id', async ctx => {

})

// ユーザーを削除する
router.delete('/:id', async ctx => {

})

// ルーティングミドルウェアを登録する
app.use(router.routes()).use(router.allowedMethods())

app.listen(3000, () => {
  console.log('サーバーがポート3000で稼働しています')
})
```
上記のコードでは、5つのルーティングメソッドを定義しており、照会、挿入、更新、削除のデータベース操作に対応しています。Prismaの初期化を完了し、後でPrisma Clientを導入したら、これらのインターフェイスを実装できます。

`nodemon`コマンドを使用してサービスを起動します。このモジュールをグローバルにインストールすることをおすすめします：
```bash
nodemon src/index.js
```

## Prisma CLI
### Prismaの依存関係をインストールする
まず、Prismaの2つの依存モジュールをインストールします：
```bash
pnpm add -D prisma 
pnpm add @prisma/client
```
このうち、`prisma`はPrismaの様々な機能を呼び出すためのCLIコマンドで、データベースマイグレーション、Prisma Clientの作成などに使用されます。以下のコマンドを実行して、`prisma`の使用方法を表示します：
```bash
npx prisma --help
```
`prisma`は7つのコマンドを提供しています：
| コマンド | 説明 |
| ---- | ---- |
| init | アプリケーションでPrismaを初期化する |
| generate | 主にPrisma Clientを生成するために使用する |
| db | データベースのスキーマとライフサイクルを管理する |
| migrate | データベースをマイグレートする |
| studio | ウェブベースのワークベンチを起動してデータを管理する |
| validate | Prismaスキーマファイルの構文が正しいかチェックする |
| format | Prismaスキーマファイルをフォーマットする（デフォルトでは`prisma/schema.prisma`） |

この記事では、これらのコマンドのうち3つを主に使用します。残りのコマンドは、自分で探索してみてください。

### Prismaを初期化する
以下のコマンドを実行して、初期化を完了します：
```bash
npx prisma init
```
このコマンドは、現在のディレクトリに`.env`ファイルと`prisma`ディレクトリを作成し、`prisma`ディレクトリに`schema.prisma`ファイルを作成します。

`.env`ファイルは環境変数を格納するために使用され、通常いくつかの設定情報が含まれます。`prisma`ディレクトリは、Prismaに関連するファイルを格納するために使用されます。現在は`schema.prisma`ファイルのみがあります。このファイルはPrismaのスキーマファイルで、データベース接続情報とモデルを定義するために使用されます。

## Prisma Schemaを設計する
### VSCプラグインをインストールする
スキーマファイルを編集する前に、VS CodeにPrismaプラグインをインストールすることをおすすめします。このプラグインは、コードの強調表示、フォーマット、オートコンプリート、定義へのジャンプ、`.prisma`ファイルのチェックなどの機能を提供し、開発体験を大幅に向上させます。

### ジェネレータを設定する
`generate`を使用してジェネレータを定義し、`provider`プロパティを通じて`prisma-client-js`と宣言します（現在はこれのみがサポートされています）。`prisma generate`コマンドを実行すると、Prisma Clientが生成され、これはデータのCRUD操作を完了するために使用されます：
```prisma
generator client {
  provider = "prisma-client-js"
}
```

### データソースを設定する
`datasource`を使用してデータソースを定義し、Prismaがデータベースに接続するために必要な情報を設定します。`provider`は接続するデータベースの種類を指定し、デフォルトでは`postgresql`です。これを`mysql`に変更します。`url`はデータベースのURLを指定します。設定を分離するために、通常`.env`ファイルに定義し、`env()`関数を通じて読み取ります：
```prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}
```
デフォルトの`.env`ファイルのデータベース接続はPostgresql用です：
```bash
DATABASE_URL=postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public
```
MySQLデータベースの接続URLは、以下の必須項目で構成されます：
| 名前 | プレースホルダ | 説明 |
| ---- | ---- | ---- |
| ホスト | HOST | データベースのIPまたはドメイン名、例えばlocalhost |
| ポート | PORT | データベースのポート、例えば3306 |
| ユーザー | USER | データベースのユーザー名、例えばroot |
| パスワード | PASSWORD | データベースのパスワード |
| データベース | DATABASE | データベース名、例えばmydb |

上記のルールに従って、MySQLのURLを定義します：
```bash
DATABASE_URL="postgresql://leapcell:leapcell123@localhost:9006/prisma"
```

### ユーザーモデルを定義する
ORMツールとして、Prismaのモデルは以下の機能を持っています：
1. アプリケーションドメインのエンティティを形成する
2. データベースのテーブル（PostgreSQLなどの関係型データベース）またはコレクション（MongoDB）にマッピングする
3. Prisma Client APIの照会の基盤を形成する
4. TypeScriptでは、Prisma Clientはモデルとそのバリアントの型定義を提供し、データベースアクセスの型安全性を保証する

モデルを定義する際、`@id()`や`@default()`などのPrismaの組み込みユーティリティ関数を使用します。例えば、`@id()`は主キーを宣言するために使用され、`@default()`はデフォルト値を設定するために使用されます。以下はUserモデルの定義です：
```prisma
model User {
  id          Int         @id @default(autoincrement())
  name        String
  email       String      @unique
  password    String
  createdTime DateTime    @default(now()) @map("created_time")
  updatedTime DateTime    @updatedAt @map("updated_time")

  @@map("user")
}
```
以下の点に注意する必要があります：
1. モデル名はデフォルトで作成されるデータテーブルの名前です。ここではモデル名は`User`で、テーブル名は`@@map("user")`を通じて小文字の`user`に設定できます。
2. 各モデルには主キーが必須であり、`@id`を使用して宣言します。
3. Prismaはフィールドの型（例えば`Int`、`String`）をデータベースの対応する型（例えば`int`と`varchar`）に変換します。
4. `@unique`は一意の値制約を示し、`user`テーブルの`email`フィールドの値は重複できません。
5. JS、TS、およびデータベースの命名規則に合わせるため、`@map()`を使用して作成時刻と更新時刻の命名をマッピングします。

## データベースを同期する
新しいプロジェクトの場合、以下のコマンドを使用してPrismaモデルをデータベースに同期できます：
```bash
npx prisma db push
```
プロジェクトに既にデータがある場合は、`prisma migrate`を使用してマイグレーションする必要がありますが、これはこの記事では扱いません。

`prisma db push`コマンドは、データベースのスキーマを作成し、Prismaスキーマを使用してデータベースを同期し、自動的に`prisma generate`コマンドを実行してPrisma Clientを生成します。

## Prisma Clientを生成する
データベースを同期する際に`prisma generate`コマンドは既に実行されています。その後、Prisma Schemaファイルが変更された場合、例えばモデルを修正した場合は、このコマンドを再度実行してPrisma Clientを再生成する必要があります。

## CRUD操作
### Prisma Clientを初期化する
Prisma Clientがあれば、CRUD操作を実行できます。初期化コードは以下の通りです：
```javascript
const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()
```
Prisma Clientのインスタンス`prisma`は豊富な型を持っており、その使い方は`prisma.model.CRUDメソッド`です。一般に使用されるAPIには以下のものがあります：
- `findMany`：複数のレコードを照会する
- `findUnique`：単一のレコードを照会する
- `create`：レコードを作成する
- `update`：レコードを更新する
- `delete`：レコードを削除する

### APIを使用してインターフェイス開発を完了する
#### ユーザーリストを照会する
`findMany`にパラメータを渡さない場合、それは`user`テーブル全体のすべてのレコードを照会し、Userモデルインスタンスの配列を返します：
```javascript
router.get('/', async ctx => {
  const users = await prisma.user.findMany()

  ctx.body = users
})
```

#### 単一のユーザーを照会する
`findUnique`メソッドの`where`を通じて照会条件を設定し、指定されたIDに基づいてユーザーレコードを照会し、Userモデルインスタンスを返します：
```javascript
// 単一のユーザーを照会する
router.get('/:id', async ctx => {
  const id = parseInt(ctx.params.id)
  const user = await prisma.user.findUnique({
    where: { id }
  })

  ctx.body = user
})
```
`ctx.params.id`から取得されるIDは文字列型であることに注意してください。照会する前に整数型に変換する必要があります。

#### ユーザーを作成する
`create`メソッドを使用してデータを挿入し、リクエストボディから解析されたデータ（Userモデルを記述するオブジェクト）を`data`プロパティに割り当てます：
```javascript
router.post('/', async ctx => {
  const user = ctx.request.body
  const newUser = await prisma.user.create({
    data: user
  })

  ctx.body = newUser
})
```

#### ユーザーを更新する
`update`メソッドを使用し、`where`を通じて照会条件を設定し、対象のユーザーを照会した後、更新するデータを`data`に割り当てます：
```javascript
router.patch('/:id', async ctx => {
  const id = parseInt(ctx.params.id)
  const updateUser = ctx.request.body

  const user = await prisma.user.update({
    where: {
      id
    },
    data: updateUser
  })

  ctx.body = user
})
```

#### ユーザーを削除する
`delete`メソッドを使用し、`where`を通じて削除するレコードの照会条件を設定します：
```javascript
router.delete('/:id', async ctx => {
  const id = parseInt(ctx.params.id)
  const user = await prisma.user.delete({
    where: {
      id
    }
  })

  ctx.body = user
})
```
`update`と`delete`メソッドを使用する際、必ず`where`条件を設定してください。そうしないと、データテーブルのすべてのレコードが更新または削除されてしまい、危険です。

## 結論
この記事では、ユーザーの作成、読み取り、更新、削除の例を通じて、KoaプロジェクトにおけるPrismaの基本的な使い方を示しました。全体のプロセスは以下の通りにまとめることができます：
1. 依存関係をインストールする
2. Prismaを初期化する
3. Prisma Schemaをセットアップする
4. データベースを同期する
5. Prisma Clientを作成する
6. Prisma Clientを使用してCRUDを実装する


# [Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)

最後に、nodejsサービスをデプロイするのに最適なプラットフォームをおすすめします：**[Leapcell](leapcell.io/?lc_t=d_prisma)**

[![brandpic7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/53965c5e-acbd-49e8-bb74-50b019181937.png)](leapcell.io/?lc_t=d_prisma)


### 🚀 好きな言語で構築する  
JavaScript、Python、Go、またはRustで簡単に開発できます。  

### 🌍 無料で無制限のプロジェクトをデプロイする  
使用した分だけ支払います — リクエストがなければ、請求もありません。  

### ⚡ 使った分だけ支払い、隠された費用はありません  
アイドル料金はなく、シームレスなスケーラビリティが備わっています。

[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/cec58e8c-03a4-438c-ab5d-1a2b94ba65e4.png)](leapcell.io/?lc_t=d_prisma)


[📖 ドキュメントを探索する](https://docs.leapcell.io/)  

🔹 Twitterでフォローしてください： [@LeapcellHQ](https://x.com/LeapcellHQ)