0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NestJS で MySQL を使う

Posted at

エンティティを作成する

@Entity('users')で TypeORM によってusersテーブルが作成・参照される。

id には@PrimaryGeneratedColumn('uuid')を設定する。これをしないと SQL では主キーが数値型扱いになり実行時エラーが出る。

import {
  Column,
  CreateDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from "typeorm";

@Entity("users")
export class User {
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @Column()
  name: string;

  @CreateDateColumn()
  readonly createdAt: Date;

  @UpdateDateColumn()
  readonly updatedAt: Date;
}

AppModule に MySQL の接続情報を記載する

src/app.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { Todo } from "./todos/entities/todo.entity";
import { TodosModule } from "./todos/todos.module";

@Module({
  imports: [
    // ★ ここから
    TypeOrmModule.forRoot({
      type: "mysql",
      host: "localhost",
      port: 3306,
      username: "user",
      password: "password",
      database: "db",
      entities: [User],
      synchronize: true, // これを入れるとMySQLの既存のデータが消える。
    }),
    // ★ ここまで
    TodosModule,
    UsersModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
  constructor(private readonly usersService: UsersService) {}

  async onModuleInit() {
    console.log("onModuleInit");
    const users = await this.usersService.findAll();
    if (users.length <= 0) {
      console.log("Create admin");
      await this.usersService.create({ name: "admin" });
    }
  }
}

ちなみにonModuleInit()に NestJS アプリケーションの起動時の処理を書くことができる。awaitも実行可能なので Service のコンストラクタに初期処理を書くよりおすすめ。

import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./entities/user.entity";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";

@Module({
  imports: [TypeOrmModule.forFeature([User])], // ★
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

Service を実装する

src/users/users.service.ts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { CreateUserDto } from "./dto/create-user.dto";
import { UpdateUserDto } from "./dto/update-user.dto";
import { User } from "./entities/user.entity";
import { UserNotFoundError } from "./errors/user-not-found-error";

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>
  ) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    const id = crypto.randomUUID();
    await this.usersRepository.save({
      id,
      name: createUserDto.name,
    });
    const user = await this.usersRepository.findOneBy({ id });
    return user;
  }

  async findAll(): Promise<User[]> {
    return await this.usersRepository.find({ order: { name: "ASC" } });
  }

  async findOne(id: string): Promise<User> {
    const user = await this.usersRepository.findOneBy({ id });
    if (!user) {
      throw new UserNotFoundError();
    }
    return user;
  }

  async update(id: string, updateUserDto: UpdateUserDto) {
    const user = await this.usersRepository.findOneBy({ id });
    if (!user) {
      throw new UserNotFoundError();
    }
    await this.usersRepository.update(id, { ...updateUserDto });
  }

  async remove(id: string) {
    const user = await this.usersRepository.findOneBy({ id });
    if (!user) {
      throw new UserNotFoundError();
    }
    await this.usersRepository.delete(id);
  }
}

Controller を実装する

src/users/users.controller.ts
import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpException,
  Param,
  Patch,
  Post,
} from "@nestjs/common";
import { CreateUserDto } from "./dto/create-user.dto";
import { UpdateUserDto } from "./dto/update-user.dto";
import { User } from "./entities/user.entity";
import { UserNotFoundError } from "./errors/user-not-found-error";
import { UsersService } from "./users.service";

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

  @Post()
  async create(@Body() createUserDto: CreateUserDto): Promise<User> {
    try {
      return await this.usersService.create(createUserDto);
    } catch (error: any) {
      this.catchError(error);
    }
  }

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

  @Get(":id")
  async findOne(@Param("id") id: string): Promise<User> {
    try {
      return await this.usersService.findOne(id);
    } catch (error: any) {
      this.catchError(error);
    }
  }

  @Patch(":id")
  async update(
    @Param("id") id: string,
    @Body() updateUserDto: UpdateUserDto
  ): Promise<User> {
    try {
      await this.usersService.update(id, updateUserDto);
      return await this.usersService.findOne(id);
    } catch (error: any) {
      this.catchError(error);
    }
  }

  @Delete(":id")
  @HttpCode(204)
  async remove(@Param("id") id: string): Promise<void> {
    try {
      return await this.usersService.remove(id);
    } catch (error: any) {
      this.catchError(error);
    }
  }

  private catchError(error: any) {
    if (error instanceof UserNotFoundError) {
      throw new HttpException("User not found", 404);
    } else {
      throw new HttpException("Internal server error", 500);
    }
  }
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?