m_shige1979のささやかな抵抗と欲望の日々

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

Typescriptで動作するDBのマイグレーションツールPrismaを触ってみた

Prisma

www.prisma.io

いくつかマイグレーションツール探していてなんか良いのがなかった

最悪、sqlでどうにかしようかなぁと思っていた。

お試し環境

node16のdockerコンテナ

docker-compose

version: "3"

services:

  # backend
  backedn:
    # コンテナ名
    container_name: node-dev
    # build
    image: node:16
    # コンテナの中に入る
    tty: true
    # 他のコンテナ起動後に起動するように制御
    depends_on:
      - db
    # ボリューム
    volumes:
      - "./app"
    # WORKDIR
    working_dir: /app
    # 環境変数
    environment:
      TZ: "Asia/Tokyo"

  # DBサーバ
  db:
    # コンテナ名
    container_name: db
    # build
    image: mysql
    # 環境設定
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_USER: root
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: sample1
      MYSQL_USER: app
      MYSQL_PASSWORD: password
    # コンテナの中に入る
    tty: true
    # ボリューム
    volumes:
      - mysql_data:/var/lib/mysql
    # ポート開放
    ports:
      - 3306:3306

# 名前付きボリュームをdockerホストの管理下で作成
volumes:
  #
  mysql_data: {}

build, up

docker-compose build
docker-compose run --rm backend bash

# node -v
v16.13.0
# npm -v
8.1.0
#

手順

プロジェクト初期化

# npm init -y
Wrote to /app/package.json:

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


#

関連パッケージをインストール

npm install --save typescript
npm install --save @types/node
npm install --save ts-node
npx tsc --init
npm install --save express
npm install --save @types/express
npm install --save-dev prisma
npm install --save @prisma/client

# cat package.json
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@prisma/client": "^3.5.0",
    "@types/express": "^4.17.13",
    "@types/node": "^16.11.9",
    "express": "^4.17.1",
    "ts-node": "^10.4.0",
    "typescript": "^4.5.2"
  },
  "devDependencies": {
    "prisma": "^3.5.0"
  }
}
#

prismaの初期化

npx prisma init

.
|-- package-lock.json
|-- package.json
|-- prisma
|   `-- schema.prisma
`-- tsconfig.json

.envprisma/schema.prismaが生成されるため、DBの情報を修正する

.env

DATABASE_URL="mysql://root:password@db:3306/sample1"

prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

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

モデルを作成する

prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

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

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?

  @@map("users")
}

マイグレーション実行

npx prisma migrate dev --name init

↓ 新規の場合はmigrationsディレクトリが作成され、SQLファイルができる

migrations/
  └─ 20211120075456_init/
    └─ migration.sql

DB構成

f:id:m_shige1979:20211120165744p:plain

適当なデータを準備

INSERT INTO users (
    `email`, `name`
) VALUES 
    ('test1@test.com', 'test1'),
    ('test2@test.com', 'test2'),
    ('test3@test.com', 'test3')
;

サンプルコード

index.ts

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

async function main() {
    const allUsers = await prisma.user.findMany({})
    console.dir(allUsers, { depth: null })
}

main()
    .catch((e) => {
        throw e
    })
    .finally(async () => {
        await prisma.$disconnect()
    })

 npx ts-node index.ts

[
  { id: 1, email: 'test1@test.com', name: 'test1' },
  { id: 2, email: 'test2@test.com', name: 'test2' },
  { id: 3, email: 'test3@test.com', name: 'test3' }
]

うん、いい感じ

所感

最初はSequelizeでいく予定でしたがテーブル名を別名で定義するところとかがうまくできなくて 困っていました。 こちらは結構わかりやすい感じ ゴリゴリ対応は最悪SQL直がきにしかないかもですがシンプルな構成の場合はやりやすいかも 次はSeedを試す

参考

Prisma - Next-generation Node.js and TypeScript ORM for Databases

次世代の Node.js ORM 、Prisma を試す

5分で終わるPrisma 2 Tutorial - valid,invalid