NestJS + Prisma

● NestJS アプリの初期化

nest new my-api

● DB (MySQL)を docker で用意する

vi docker-compose.yml

version: "3.8"
services:
  db:
    container_name: translate-api-db
    image: mysql:8.0
    restart: always
    ports:
      - 13306:3306
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: translate_api_db
      MYSQL_USER: translate_api_db
      MYSQL_PASSWORD: db_password
    volumes:
      - ./db/data:/var/lib/mysql

docker で mysqlの起動

docker compose up

● PrismaでDB接続の作成

(Prisma) 1. ・Prisma CLIとPrisma Clientをインストール

cd my-api
npm install @prisma/client
npm install --save-dev prisma

(Prisma) 2. ・Prismaのセットアップ

npx prisma init

ディレクトリ直下に 2つのファイル prisma/schema.prisma.env が生成されます

(Prisma) 3. ・prisma/schema.prisma の 変更

データベースがMySQLの場合は以下のように修正します

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

(Prisma) 4. ・.env の 変更

.env 例えば以下のように設定します

DATABASE_URL="mysql://adi_db:adi_db_pass@localhost:3307/adi_db?schema=public"

コンテナ名を指定する場合は

DATABASE_URL="mysql://adi_db:adi_db_pass@docker-nest-db-1/adi_db?schema=public"

● Prisma のDBマイグレーション

schema.prisma に テーブル情報を追記します

model User {
  id          Int           @id @default(autoincrement())
  email       String        @db.Text
  name        String        @db.Text
  createdAt   DateTime      @default(now()) @db.Timestamp(0)
  updatedAt   DateTime      @default(now()) @updatedAt @db.Timestamp(0)
  source      Source[]      @relation("source_fk_1")
}

model Source {
  id          Int           @id @default(autoincrement())
  userId      Int         
  user        User          @relation(name: "source_fk_1", fields: [userId], references: [id])
  text        String        @db.Text
  translation Translation[] @relation("translation_fk_1")
}

model Translation {
  id          Int           @id @default(autoincrement())
  sourceId    Int
  source      Source        @relation(name: "translation_fk_1", fields: [sourceId], references: [id])
  locale      String        @db.VarChar(8)
  text        String        @db.Text
}

マイグレーション時に仮のテーブルを作成するので権限を付与します。

d exec -it <コンテナ名> bash
mysql -uroot -p mysql
create user translate_api_db@localhost identified by 'db_password';
grant create, alter, drop, references on *.* to translate_api_db;

実行後は exit でコンテナから抜けます。

次のコマンドでマイグレーションを実行します

npx prisma migrate dev

マイグレーションファイル名を入力されるので、次のように 行った操作を簡単に入力します。(実行日時は自動的にセットされます)

add_tables

実行すると

  1. DBへテーブル Todo が作成されます
  2. 実行されたsql文が次のファイル名にて保存されます prisma/migrations/20230321072643_add_tables/migration.sql

・ マイグレーションの ロールバックコマンドは用意されていません

本番サーバーではロールバックすることがない(修正する場合は、修正するバイブレーションを追加すると言う方式)ため

・ マイグレーション関連コマンド

# データベースをリセットしDBへ反映
npx prisma migrate reset

# マイグレーションのステータスチェック
npx prisma migrate status

# マイグレーションの実行・DBへ反映
npx prisma migrate deploy

# 型情報の生成
npx prisma generate

・ Prisma Studioの起動

npx prisma studio

package.json に追加しておくと、コマンド覚えなくていいです。

  "scripts": {
     .............
    "prisma:studio": "dotenv -e .env.development -- npx prisma studio",
  }
"prisma:studio": "dotenv -e .env.development -- npx prisma studio",

・マイグレーションのロールバック

Prisma2でDB Resetを無理やり行う

● Prisma のDBシーダーの実行

・シーダーファイルの作成

ファイル名 /prisma/seed.ts を作成します。

vi prisma/seed.ts

prisma/seed.ts を 以下の内容で保存します

import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient();

const insertData: Prisma.TodoCreateInput[] = [
  {
    title: 'タイトル01',
    description: '説明01',
    status: 'AAA01',
    createdAt: new Date(),
    updatedAt: new Date(),
  },
  {
    title: 'タイトル02',
    description: '説明02',
    status: 'AAA02',
    createdAt: new Date(),
    updatedAt: new Date(),
  },
];

const transfer = async () => {
  const coffeeShops = insertData.map((c) => {
    return prisma.todo.create({ data: c });
  });
  return await prisma.$transaction(coffeeShops);
};

const main = async () => {
  await transfer();
};

main()
  .then(() => {
    console.log('seed finished.');
  })
  .catch((e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

・package.json へ追加

package.json 次のコードを追記します

  "prisma": {
    "seed": "ts-node ./prisma/seed.ts"
  },  

・シーダーを実行する

npx prisma db seed

または 直接ファイルを実行してもokです

npx ts-node prisma/seed.ts 
No.2301
05/08 12:05

edit