29
13

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.

Nest.jsのORMにPrismaを導入してみる

Last updated at Posted at 2022-06-08

はじめに

Nest.jsでアプリを作る際に、typeORMではなくPrismaを使いたかったので、その導入方法についてと簡単な使い方

Prismaとは

Prismaについてテキトーに公式ドキュメントから引用しておきます。

Prisma is an open-source ORM for Node.js and TypeScript. It is used as an alternative to writing plain SQL, or using another database access tool such as SQL query builders (like knex.js) or ORMs (like TypeORM and Sequelize). Prisma currently supports PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and CockroachDB (Preview).

PrismaはNode.jsとTypeScriptのためのオープンソースのORMです。SQLクエリビルダ(knex.jsなど)やORM(TypeORMやSequelizeなど)などのデータベースアクセスツールの代替として使用されます。Prismaは現在、PostgreSQL、MySQL、SQL Server、SQLite、MongoDB、CockroachDB (Preview)をサポートしています。

While Prisma can be used with plain JavaScript, it embraces TypeScript and provides a level to type-safety that goes beyond the guarantees other ORMs in the TypeScript ecosystem.

PrismaはプレーンなJavaScriptで使用できますが、TypeScriptを採用し、TypeScriptエコシステムの他のORMの保証を超えるレベルの型安全性を提供します。

typeORMとの比較についてはこちら↓

Nest.jsにPrismaを導入する

まずはnestのプロジェクトのディレクトリに移動して、Primsaをインストールします。

$ cd nest-app
$ npm install prisma --save-dev

下記のように、npxをプレフィックスとしてローカルでPrisma CLIを起動し、
initコマンドを使用して、Prismaの初期設定を作成します。

$ npx prisma
$ npx prisma init

initコマンドを実行するとprismaディレクトリと、その配下にschema.prismaというファイルが作成されます。

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

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

データベース接続は、schema.prismaファイルのdatasourceブロックで設定します。

デフォルトでは、sqliteに設定されています。

今回はmysqlを使います。

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

generator client {
  provider = "prisma-client-js"
}
.env
DATABASE_URL="mysql://USER:PASSWORD@HOST:PORT/DATABASE"

※USERやPASSWORDなど大文字の部分は自分のものに変更してください

schema.prismaにUserモデルを作成

続いてschema.prismaにモデルを定義します。

今回は試しにUserモデルを作成します。

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

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

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

モデルを定義したら下記コマンドでマイグレートします。

$ npx prisma migrate dev --name init

上記のコマンドを実行すると、下記のようにmigrationsディレクトリとその配下にマイグレーションファイルが作成されます。

prisma
├── migrations
│   └── 20220602083421_init
│       └── migration.sql
└── schema.prisma
prisma/migrations/20220602083421_init/migration.sql
-- CreateTable
CREATE TABLE `User` (
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(191) NOT NULL,
    `name` VARCHAR(191) NULL,

    UNIQUE INDEX `User_email_key`(`email`),
    PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Prisma Clientのインストール

続いて、下記コマンドでPrisma Clientをインストールします。

Prisma Clientは、Prismaのモデル定義から生成されるタイプセーフのデータベースクライアントです。

$ npm install @prisma/client

インストール時に、Prismaは自動的にprisma generateコマンドを呼び出します。
なので、次回以降Prismaモデルを変更するたびにこのコマンドを実行し、生成されたPrismaクライアントを更新する必要があります。

PrismaServiceの作成

続いて、PrismaClientのインスタンス化とデータベースへの接続を行うPrismaServiceを作成します。

srcディレクトリ内にprisma.service.tsというファイルを新規に作成し、下記のコードを追加します。

src/prisma.service.ts
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }

  async enableShutdownHooks(app: INestApplication) {
    this.$on('beforeExit', async () => {
      await app.close();
    });
  }
}

UsersServiceの作成

Prismaスキーマから、先程作成したUserモデルのデータベースを呼び出すために使用するUsersServiceを作成します。

srcディレクトリの中にusersディレクトリとusers.service.tsというファイルを新規に作成し、下記のコードを追加します。

下記コマンドでも作成できます。

$ nest g service users
src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaService } from './prisma.service';
import { User, Prisma } from '@prisma/client';

@Injectable()
export class UsersService {
  constructor(private prisma: PrismaService) {}

  async user(
    id: number,
  ): Promise<User | null> {
    return this.prisma.user.findUnique({
      where: { id }
    });
  }

  async users(): Promise<User[]> {
    return this.prisma.user.findMany();
  }

  async createUser(data: Prisma.UserCreateInput): Promise<User> {
    return this.prisma.user.create({
      data,
    });
  }
}

ルーティングとコントローラを追加

続いて、先程作成したサービスを使用して、ルーティングとコントローラを定義します。

usersディレクトリの中にusers.controller.tsというファイルを新規に作成し、下記のコードを追加します。

下記コマンドでも作成できます。

$ nest g controller users
src/users/users.controller.ts
import {
  Controller,
  Get,
  Param,
  Post,
  Body,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from '@prisma/client';

@Controller('users')
export class UsersController {
  constructor(
    private readonly usersService: UsersService,
  ) {}

  @Get(':id')
  async findUserById(
  @Param('id') id: string,
  ): Promise<User> {
    return this.usersService.user(Number(id));
  }

  @Get()
  async users(): Promise<User[]> {
    return this.usersService.users();
  }

  @Post()
  async createUser(
    @Body() userData: { name?: string; email: string },
  ): Promise<User> {
    return this.usersService.createUser(userData);
  }
}

モジュールを追加

最後にUsersModuleを作成し、AppModuleに追加します。

users配下にusers.module.tsというファイルを作成し、下記コードを追加します。

下記コマンドでも作成できます。

$ nest g module users
src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { PrismaService } from '../prisma.service';

@Module({
  controllers: [UsersController,],
  providers: [UsersService, PrismaService]
})
export class UserModule {}
src/app.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';

@Module({
  imports: [UsersModule],
})
export class AppModule {}

これでNest.jsにPrismaを導入し、アプリケーションからDBを操作できるようになりました

curlコマンドなどで試してみてください!

$ curl -H "content-type: application/json" -X POST -d'{"name":"田中太郎", "email":"tanaka@sample.com"}' http://localhost:3000/users
=> {"id":1,"name":"田中太郎","email":"tanaka@sample.com"}

$ curl -X GET http://localhost:3000/users/1
=> {"id":1,"name":"田中太郎","email":"tanaka@sample.com"}

$ curl -X GET http://localhost:3000/users
=> [{"id":1,"name":"田中太郎","email":"tanaka@sample.com"}]

参考

29
13
1

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
29
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?