8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Prisma を触ってみる

Posted at

Typescript 製 ORM の Prisma の主要機能を触ってみたいと思います。
チュートリアルのデータベースを新規に作成する開発パターン をベースに機能を試して行きます。

初期設定

  • 必要なものを install する
    • devDependencies
      • typescript
      • prisma
      • ts-node
      • @types/node
    • dependencies
      • @prisma/client
  • npx prisma init する
  • DB の接続情報を設定する

migrate

こちらを参考に schemaファイル (schema.prisma) に user, post, profile の schema を記載します。

次に上記を参考に npx prisma migrate dev --name init を実行します。

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

- Drift detected: Your database schema is not in sync with your migration history.

The following is a summary of the differences between the expected database schema given your migrations files, and the actual schema of the database.

It should be understood as the set of changes to get from the expected schema to the actual schema.

[+] Added tables
  - Post
  - Profile
  - User

[*] Changed the `Post` table
  [+] Added foreign key on columns (authorId)

[*] Changed the `Profile` table
  [+] Added foreign key on columns (userId)

- The following migration(s) are applied to the database but missing from the local migrations directory: 20211231005805_init

✔ We need to reset the MySQL database "mydb" at "db:3306".
Do you want to continue? All data will be lost. … yes

Applying migration `20211231010444_init`

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

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

Your database is now in sync with your schema.

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

4つの table が作成されていることを確認できました。

MySQL [mydb]> show tables;
+--------------------+
| Tables_in_mydb     |
+--------------------+
| Post               |
| Profile            |
| User               |
| _prisma_migrations |
+--------------------+
4 rows in set (0.005 sec)

migrate dev の dev とは開発環境で実行するモードのようです。

migrate dev は migration ファイルを作成した後にすぐに適用されます。

--create-only を追加することで migration ファイルを作成するだけに留めることができます。

データを読み取る

DBにデータを追加します。

INSERT INTO `User` (`email`, `name`) VALUES ('hoge@example.com', 'hoge');

以下 index.ts を用意します。

index.ts
import {PrismaClient} from '@prisma/client'

const prisma = new PrismaClient()

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

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

以下のように読みとることができます。

$ npx ts-node src/index.ts
[ { id: 1, email: 'hoge@example.com', name: 'hoge' } ]

データの書き込み

先ほどの index.ts の main を書き換えて実行します。

index.ts
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 })
}
$ npx ts-node src/index.ts
[
  {
    id: 1,
    email: 'alice@prisma.io',
    name: 'Alice',
    posts: [
      {
        id: 1,
        createdAt: 2021-12-31T08:29:02.391Z,
        updatedAt: 2021-12-31T08:29:02.392Z,
        title: 'Hello World',
        content: null,
        published: false,
        authorId: 1
      }
    ],
    profile: { id: 1, bio: 'I like turtles', userId: 1 }
  }
]

新規作成した user と紐付いた, post, profile が作成されていることがわかります。

client を更新する

model を更新した際、prisma generate で更新します。

After you change your data model, you'll need to manually re-generate Prisma Client to ensure the code inside node_modules/.prisma/client gets updated: $ prisma generate

ここにわかりやすい更新のフローがあります。

試しに先ほどの model User に address カラムを追加し、prisma generate を実行します。

npx prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma

✔ Generated Prisma Client (3.7.0 | library) to ./node_modules/@prisma/client in 324ms
You can now start using Prisma Client in your code. Reference: https://pris.ly/d/client

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

クライアントが更新されたので、エディタの complete で表示してくれるようになりました。

スクリーンショット 2022-01-01 22.21.12.png

transaction

transaction も利用することができます

data load (seeding)

データのロード機能もあります。
Prisma モデルを利用した TypeScript ファイルを実行したり、shell で実行することができるようです。

試してみます。
prisma/seed.ts を作成して以下のコードを貼り付けます。

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

async function main() {
    const alice = await prisma.user.upsert({
        where: { email: 'alice@prisma.io' },
        update: {},
        create: {
            email: 'alice@prisma.io',
            name: 'Alice',
            posts: {
                create: {
                    title: 'Check out Prisma with Next.js',
                    content: 'https://www.prisma.io/nextjs',
                    published: true,
                },
            },
        },
    })

    const bob = await prisma.user.upsert({
        where: { email: 'bob@prisma.io' },
        update: {},
        create: {
            email: 'bob@prisma.io',
            name: 'Bob',
            posts: {
                create: [
                    {
                        title: 'Follow Prisma on Twitter',
                        content: 'https://twitter.com/prisma',
                        published: true,
                    },
                    {
                        title: 'Follow Nexus on Twitter',
                        content: 'https://twitter.com/nexusgql',
                        published: true,
                    },
                ],
            },
        },
    })
    console.log({ alice, bob })
}

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

package.json ファイルに seeding script をキックするための設定を追加します。

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

npx prisma db seed で seeding を実行します。

$ npx prisma db seed 
Environment variables loaded from .env
Running seed command `ts-node prisma/seed.ts` ...
{
  alice: { id: 1, email: 'alice@prisma.io', name: 'Alice' },
  bob: { id: 2, email: 'bob@prisma.io', name: 'Bob' }
}

🌱  The seed command has been executed.

:seedling: が芽生えてデータをロードすることができました。

触った感想

  • model が型で補完をしてくれるので快適
  • エラーメッセージが丁寧
  • ドキュメントが丁寧

ORM は使い込まないと評価はできないと思うのですが、
少し触ってみた感想としてはとても良かったので続けて触ってみたいと思います。

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?