【NodeJS】PrismaやTypeScript、MySQLを使ってデータを操作する

Node.js

1. 概要

今回はPrismaを使ってMySQLにデータを登録しながら抽出まで行う内容になります。

前回はSQLiteを使いました。

対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。

2. Prismaとは

  • ORM for Node.js & Typescript

Node.jsとTypeScriptで利用できるORM(Object Relational Mapping)のようです。

Prisma | Next-generation ORM for Node.js & TypeScript

3. nodeのインストール

こちらを参考

ここからは公式サイトの手順に従い、やってみます。

4. プロジェクトを作成

mkdir hello-prisma-mysql
cd hello-prisma-mysql

5. 必要なライブラリをインストール

npm init -y
npm install prisma typescript ts-node @types/node --save-dev

6. セットアップ

npx tsc --init
npx prisma init

7. Databaseへ接続設定

touch .env
DATABASE_URL="mysql://user:password@localhost:3306/mydb"

※「prisma/schema.prisma」を修正

  • 変更前
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
  • 変更後
    • 「postgresql」⇒「mysql」
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

8. スキーマを定義

※「prisma/schema.prisma」に追加

model Post {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title     String   @db.VarChar(255)
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

model Profile {
  id     Int     @id @default(autoincrement())
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  name    String?
  posts   Post[]
  profile Profile?
}
  • model「Post」「Profile」「User」を追加

9. MySQLを起動

こちらを参考

docker-compose up -d

※「user」にパーミッションを付与

docker-compose exec mysql-server bash
# コンテナ内でrootでmysqlに接続
$ mysql -uroot -proot mysql

# mysql内でALL権限付与
mysql> GRANT ALL ON *.* TO 'user';

# 反映
mysql> FLUSH PRIVILEGES;

10. スキーマを作成

npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "mydb" at "localhost:3306"

MySQL database mydb created at localhost:3306

Applying migration `20230711080111_init`

The following migration(s) have been created and applied from new schema changes:

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

Your database is now in sync with your schema.

Running generate... (Use --skip-generate to skip the generators)

added 2 packages, and audited 24 packages in 7s

found 0 vulnerabilities

✔ Generated Prisma Client (4.16.2 | library) to ./node_modules/@prisma/client in 84ms

11. スキーマを確認

docker-compose exec mysql-server mysql -hlocalhost -uuser -p mydb

OR

mysql -hlocalhost -uuser -p mydb --protocol=tcp
mysql> SHOW TABLES;
+--------------------+
| Tables_in_mydb     |
+--------------------+
| Post               |
| Profile            |
| User               |
| _prisma_migrations |
+--------------------+
4 rows in set (0.00 sec)

12. Prismaクライアントをインストール

npm install @prisma/client

13. データを登録

※src/create-data.ts

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
  await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@prisma.io',
      posts: {
        create: { title: 'Hello World' },
      },
      profile: {
        create: { bio: 'I like turtles' },
      },
    },
  })

  const allUsers = await prisma.user.findMany({
    include: {
      posts: true,
      profile: true,
    },
  })
  console.dir(allUsers, { depth: null })
}

main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

実行

npx ts-node src/create-data.ts
[
  {
    id: 1,
    email: 'alice@prisma.io',
    name: 'Alice',
    posts: [
      {
        id: 1,
        createdAt: 2023-07-11T11:11:25.280Z,
        updatedAt: 2023-07-11T11:11:25.280Z,
        title: 'Hello World',
        content: null,
        published: false,
        authorId: 1
      }
    ],
    profile: { id: 1, bio: 'I like turtles', userId: 1 }
  }
]

確認

mysql> SELECT * FROM User;
+----+-----------------+-------+
| id | email           | name  |
+----+-----------------+-------+
|  1 | alice@prisma.io | Alice |
+----+-----------------+-------+
1 row in set (0.01 sec)

mysql> SELECT * FROM Post;
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
| id | createdAt               | updatedAt               | title       | content | published | authorId |
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
|  1 | 2023-07-11 11:11:25.280 | 2023-07-11 11:11:25.280 | Hello World | NULL    |         0 |        1 |
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
1 row in set (0.00 sec)

mysql> SELECT * FROM Profile;
+----+----------------+--------+
| id | bio            | userId |
+----+----------------+--------+
|  1 | I like turtles |      1 |
+----+----------------+--------+
1 row in set (0.00 sec)

14. データを取得

※src/select-data.ts

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
  const allUsers = await prisma.user.findMany()
  console.log(allUsers)
}

main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

実行

npx ts-node src/select-data.ts
[ { id: 1, email: 'alice@prisma.io', name: 'Alice' } ]

15. データを更新

※src/update-data.ts

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
  const post = await prisma.post.update({
    where: { id: 1 },
    data: { published: true },
  })
  console.log(post)
}

main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

実行

npx ts-node src/update-data.ts
{
  id: 1,
  createdAt: 2023-07-11T11:11:25.280Z,
  updatedAt: 2023-07-11T11:15:16.263Z,
  title: 'Hello World',
  content: null,
  published: true,
  authorId: 1
}

確認

mysql> SELECT * FROM Post;
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
| id | createdAt               | updatedAt               | title       | content | published | authorId |
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
|  1 | 2023-07-11 11:11:25.280 | 2023-07-11 11:15:16.263 | Hello World | NULL    |         1 |        1 |
+----+-------------------------+-------------------------+-------------+---------+-----------+----------+
1 row in set (0.00 sec)
  • 「published」が「0」から「1」へ更新

16. ディレクトリの構造

.
├── package-lock.json
├── package.json
├── prisma
│   ├── migrations
│   │   ├── 20230711080111_init
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   └── schema.prisma
├── src
│   ├── create-data.ts
│   ├── select-data.ts
│   └── update-data.ts
└── tsconfig.json

4 directories, 9 files

17. 備考

今回は公式サイトの手順に従い、PrismaとMySQLを使ってデータを操作するシンプルな内容でした。

18. 参考

投稿者プロフィール

Sondon
開発好きなシステムエンジニアです。
卓球にハマってます。

関連記事

  1. Node.js

    【NodeJS】PrismaやTypeScriptを使ってデータを操作…

最近の記事

  1. AWS
  2. flutter

制作実績一覧

  1. Checkeys