42
17

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 3 years have passed since last update.

TypeScriptでORMのPrismaに入門した

Last updated at Posted at 2021-06-22

はじめに

PrismaはNode.jsとTypeScript用のORMです。
次のツール群で構成されています。

  • Prisma Client
  • Prisma Migrate
  • Prisma Studio

https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch-typescript-postgres に記載されている手順で、プロジェクト作成を作成しPrismaを触ってみました。

※ Prisma Studioの部分に関しては、試していないので記載していません。

実行環境

バージョン
npm 6.14.7
node v14.7.0
prisma 2.25.0
@prisma/client 2.25.0

プロジェクト作成

$ mkdir hello-prisma 
$ cd hello-prisma
$ npm init -y
$ npm install prisma typescript ts-node @types/node --save-dev

tsconfig.jsonを作成して、以下の内容を記載します。

tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "outDir": "dist",
    "strict": true,
    "lib": ["esnext"],
    "esModuleInterop": true
  }
}

以下のコマンドを実行すると、.envファイルとprisma/schema.prismaが作成されます。

$ npx prisma init

データベースの準備

データベースはPostgreSQLを使用するので、Dockerを使ってPostgreSQLの準備をします。
(ここは公式サイトには記載がない内容です)
docker-compose.ymlを作成し、docker compose up -dを実行する。

docker-compose.yml
version: "3"
services:
  db:
    image: postgres:13.3
    environment:
      POSTGRES_USER: sample
      POSTGRES_PASSWORD: password
    ports:
      - 5432:5432
    volumes:
      - postgres:/var/lib/postgresql
volumes:
  postgres:

データベースに接続する

PostgreSQLを使用するので、自動生成されたprisma/schema.prismaのままで変更はありません。

prisma/schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

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

データベースへの接続URLは.envファイルから取得しているので、Dockerで起動したPostgreSQLに接続できるように変更します。
URLはpostgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMAの形式で設定します。
USERPASSWORDは、docker-compose.ymlで指定したPOSTGRES_USERPOSTGRES_PASSWORDの値になります。

.env
DATABASE_URL="postgresql://sample:password@localhost:5432/mydb?schema=public"

データベースとテーブルの作成

prisma/schema.prismaに作成するテーブルの定義を追記し、migrateを実行します。

prisma/schema.prisma
model Post {
  id        Int      @default(autoincrement()) @id
  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     @default(autoincrement()) @id
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model User {
  id      Int      @default(autoincrement()) @id
  email   String   @unique
  name    String?
  posts   Post[]
  profile Profile?
}
$ npx prisma migrate dev --name init

prisma/migrations/20210622135843_init/migration.sqlが作成されます。

Prisma Clientをインストール

$ npm install @prisma/client

クエリの実行

Prisma Clientを生成したので、スクリプトからデータベースに対してクエリを実行します。

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()
  })

index.tsを実行してデータベースからデータを取得してみます。

$ npx ts-node index.ts
[]

Userテーブルの全レコードを取得するクエリを実行していますが、まだ何もデータが登録されていないので[]が出力されます。
User/Post/Profileにデータを作成してから、取得クエリを実行します。

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 index.ts
[
  {
    id: 1,
    email: 'alice@prisma.io',
    name: 'Alice',
    posts: [
      {
        id: 1,
        createdAt: 2021-06-22T14:15:54.213Z,
        updatedAt: 2021-06-22T14:15:54.214Z,
        title: 'Hello World',
        content: null,
        published: false,
        authorId: 1
      }
    ],
    profile: { id: 1, bio: 'I like turtles', userId: 1 }
  }
]

Postテーブルのpublishedカラムをtrueに更新します。

index.ts
async function main() {
  const post = await prisma.post.update({
    where: { id: 1 },
    data: { published: true },
  })
  console.log(post)
}
$ npx ts-node index.ts
{
  id: 1,
  createdAt: 2021-06-22T14:15:54.213Z,
  updatedAt: 2021-06-22T14:21:05.080Z,
  title: 'Hello World',
  content: null,
  published: true,
  authorId: 1
}

おまけ:実行されるSQLを確認する

実際にどういうSQLが発行されているのか知りたい場合は、ログ出力すれば確認できます。
PrismaClientのインスタンスを生成する際の引数に{ log: ['query']}を渡すと、実行されるSQLのログが出力されます。

index.ts
- const prisma = new PrismaClient()
+ const prisma = new PrismaClient({ log: ['query']})
$ npx ts-node index.ts
prisma:query SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1
[ { id: 1, email: 'alice@prisma.io', name: 'Alice' } ]

さいごに

基本的に公式サイトに記載されている通りの手順で進めたので、詰まるところはありませんでした。
今回使われていないPrisma ClientのAPIがまだまだたくさんあるので、色々触っていこうと思います。

42
17
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
42
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?