0
0

More than 1 year has passed since last update.

【NestJS初心者】管理画面API作ったよって話② 〜TypeOrm データベース作成して、接続するぞ!〜

Posted at

前回は、Nestjsのプロジェクトをダウンロードして、環境構築まで完了しました。
今回は、TypeOrmを使用して、データベースの作成〜接続までを行っていこうと思います!

Nest.js公式サイト(データベース編)
typeormの公式サイトはこちら

環境

Node.js v16.10.0
MySQL v8.0.28
TypeOrm
macOS

まずは、Mysql起動

 $ mysql.server startを使用して、mysqlを起動

$ mysql.server start
Starting MySQL
 SUCCESS! 

MySQLログイン

mysql -u rootを使用してMySQLにログイン

$ mysql -u root 

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.28 Homebrew

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

※もし、Permission deniedのエラーが出る場合は、

$ sudo mysql -u root 

を使って実行が必要です。

userとpasswordを作成します。

mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
順調!順調!

データベースを作成します。

今回は、admin_infoという名前で、データベースを作成する。

mysql> create database admin_info;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| admin_info         |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

できてる〜〜〜✨

ここまでできたら、プロジェクトのアプリケーションの方でTypeOrmの設定に入ります!

TypeOrmの設定

TypeOrmのパッケージ等を追加

$ yarn add @nestjs/typeorm
$ yarn add typeorm
$ yarn add mysql

TypeOrmModuleの設定をapp.module.tsに追記する

//app.module.ts
import { TypeOrmModule } from '@nestjs/typeorm';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AdminController } from './admin/admin.controller';
import { AdminService } from './admin/admin.service';
@Module({
  imports: [
   //ここから
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'password',
      database: 'admin_info',
      entities: [],
      autoLoadEntities: true,
      synchronize: false,
    }),
  //ここまで
  ],
  controllers: [AppController, AdminController],
  providers: [AppService, AdminService],
})
export class AppModule {}

一回試しに$ yarn run startで起動させてみる!

[Nest] 86006  - 2022/02/04 23:38:06     LOG [NestFactory] Starting Nest application...
[Nest] 86006  - 2022/02/04 23:38:06     LOG [InstanceLoader] TypeOrmModule dependencies initialized +95ms
[Nest] 86006  - 2022/02/04 23:38:06     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 86006  - 2022/02/04 23:38:06   ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)...
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
    at Handshake.Sequence._packetToError 
    at Handshake.ErrorPacket 
    at Protocol._parsePacket 
    at Parser._parsePacket 
    at Parser.write
    at Protocol.write
    at Socket.<anonymous> 
    at Socket.<anonymous> 
    at Socket.emit (node:events:390:28)

.....
[Nest] 85968  - 2022/02/04 23:38:13   ERROR [ExceptionHandler] ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
.
.
.


エラー出た_:(´ཀ`」 ∠):

ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client .....
クライアントが、サーバから要求された認証プロトコルをサポートしていない.....
え( ^∀^)?

ググる。

原因・解決策

MySQLでパスワードの認証形式が変更されているが、
Node.jsの「mysql」にはまだ実装されていないことが原因らしかった、、、

認証方法をmysql_native_passwordに変更することで、この問題は解決できました!
下記のコマンドをmysqlで実行!

mysql> ALTER USER 'user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'
$ yarn run start

[Nest] 86713  - 2022/02/04 23:59:39     LOG [NestFactory] Starting Nest application...
[Nest] 86713  - 2022/02/04 23:59:39     LOG [InstanceLoader] TypeOrmModule dependencies initialized +96ms
[Nest] 86713  - 2022/02/04 23:59:39     LOG [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 86713  - 2022/02/04 23:59:39     LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +9ms
[Nest] 86713  - 2022/02/04 23:59:39     LOG [RoutesResolver] AppController {/}: +11ms
[Nest] 86713  - 2022/02/04 23:59:39     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 86713  - 2022/02/04 23:59:39     LOG [NestApplication] Nest application successfully started +2ms

動いたぁぁぁ💓

MySQLとの接続は完了したようなので、
テーブル作成に移ります!

テーブル作成

テーブルを作成するにあたり、
- entityファイル
- migrationファイル(自動生成されます)
- ormconfigファイル

の3つを新規作成していきます。

まずは、
src配下にtypeormのフォルダを作成し、さらにentitymigrationフォルダを追加。
entityフォルダの中にadmin_info.entity.tsファイルを作成。
アプリケーション直下にorm.configファイルを作成。

.
├── src
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   ├── main.ts
│   └── typeorm←これ追加する
│       ├── entity←これ追加する
│       └── migration←これ追加する
├── ormconfig.ts←これ追加する

①Entityを作成していきます。

今回は、このようなテーブルを作成していこうと思います!
テーブル名:author_info

カラム名 データ型 メモ
Id number ID
user string ユーザー名
status number ステータス
imagePhotoPath string 写真
description string 説明
createdAt Date 作成日
updatedAt Date アップデート日

admin_info.entity.tsファイルの中に
作成したいカラムを下記のように書いていきます。

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

  @Entity({ name: 'admin_info' })
  export class AdminInfo extends BaseEntity {
    @PrimaryGeneratedColumn()
    id!: number;
    @Column({ name: 'user', unique: true })
    user!: string;
    @Column({ name: 'status' })
    status!: number;
    @Column({ name: 'image_photo_path' })
    imagePhotoPath!: string;
    @Column({ name: 'description', default: 0 })
    description!: string;
    @CreateDateColumn({ name: 'created_at' })
    createdAt!: Date;
    @UpdateDateColumn({ name: 'updated_at' })
    updatedAt: Date;
  }

②ormconfig.tsの設定

その次に、ormconfig.tsに下記のように設定を記載。

module.exports = {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'user',
    password: 'password',
    database: 'admin_info',
    entities: ['dist/src/typeorm/entity/**/*.js'],
    migrations: ['dist/src/typeorm/migration/**/*.js'],
    subscribers: ['dist/src/typeorm/subscriber/**/*.js'],
    synchronize: false,
    logging: false,
    cli: {
      migrationsDir: 'src/typeorm/migration',
    },
  };
// アプリケーションを再起動。
$ yarn run start

yarn run v1.22.11
$ nest start
[Nest] 87256  - 2022/02/05 0:20:11     LOG [NestFactory] Starting Nest application...
[Nest] 87256  - 2022/02/05 0:20:11     LOG [InstanceLoader] TypeOrmModule dependencies initialized +63ms
[Nest] 87256  - 2022/02/05 0:20:11     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 87256  - 2022/02/05 0:20:11     LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +15ms
[Nest] 87256  - 2022/02/05 0:20:11     LOG [RoutesResolver] AppController {/}: +6ms
[Nest] 87256  - 2022/02/05 0:20:11     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 87256  - 2022/02/05 0:20:11     LOG [NestApplication] Nest application successfully started +2ms

③マイグレーションスクリプトの生成

最後に、マイグレーションスクリプトの生成します!
今回は自動生成しようと思うので、

$ yarn ts-node node_modules/.bin/typeorm migration:generate -n (マイグレーション名)

を実行。
※今回はマイグレーション名をinitとしました。

Migration /path/your/app/admin-app/src/typeorm/migration/1643988029988-init.ts has been generated successfully.
  Done in 2.09s.

先ほど作った/typeorm/migrationファイルの中にマイグレーションファイルが自動生成されました!

やった〜!

///typeorm/migrationファイルの中身
import {MigrationInterface, QueryRunner} from "typeorm";

export class init1643988029988 implements MigrationInterface {
    name = 'init1643988029988'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TABLE \`admin_info\` (\`id\` int NOT NULL AUTO_INCREMENT, \`user\` varchar(255) NOT NULL, \`status\` int NOT NULL, \`image_photo_path\` varchar(255) NOT NULL, \`description\` varchar(255) NOT NULL DEFAULT '0', \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_83114dcb0b3c33b8018f811d4f\` (\`user\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`DROP INDEX \`IDX_83114dcb0b3c33b8018f811d4f\` ON \`admin_info\``);
        await queryRunner.query(`DROP TABLE \`admin_info\``);
    }

}

出来てる( ´∀`)出来てる( ´∀`)

マイグレーションの実行

$ yarn ts-node node_modules/.bin/typeorm migration:run
query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = 'admin_info' AND `TABLE_NAME` = 'migrations'
query: CREATE TABLE `migrations` (`id` int NOT NULL AUTO_INCREMENT, `timestamp` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB
query: SELECT * FROM `admin_info`.`migrations` `migrations` ORDER BY `id` DESC
0 migrations are already loaded in the database.
1 migrations were found in the source code.
1 migrations are new migrations that needs to be executed.
query: START TRANSACTION
query: CREATE TABLE `admin_info` (`id` int NOT NULL AUTO_INCREMENT, `user` varchar(255) NOT NULL, `status` int NOT NULL, `image_photo_path` varchar(255) NOT NULL, `description` varchar(255) NOT NULL DEFAULT '0', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_83114dcb0b3c33b8018f811d4f` (`user`), PRIMARY KEY (`id`)) ENGINE=InnoDB
query: INSERT INTO `admin_info`.`migrations`(`timestamp`, `name`) VALUES (?, ?) -- PARAMETERS: [1643988029988,"init1643988029988"]
Migration init1643988029988 has been executed successfully.
query: COMMIT
  Done in 2.15s.
mysql> show columns from admin_info;
+------------------+--------------+------+-----+----------------------+--------------------------------------------------+
| Field            | Type         | Null | Key | Default              | Extra                                            |
+------------------+--------------+------+-----+----------------------+--------------------------------------------------+
| id               | int          | NO   | PRI | NULL                 | auto_increment                                   |
| user             | varchar(255) | NO   | UNI | NULL                 |                                                  |
| status           | int          | NO   |     | NULL                 |                                                  |
| image_photo_path | varchar(255) | NO   |     | NULL                 |                                                  |
| description      | varchar(255) | NO   |     | 0                    |                                                  |
| created_at       | datetime(6)  | NO   |     | CURRENT_TIMESTAMP(6) | DEFAULT_GENERATED                                |
| updated_at       | datetime(6)  | NO   |     | CURRENT_TIMESTAMP(6) | DEFAULT_GENERATED on update CURRENT_TIMESTAMP(6) |
+------------------+--------------+------+-----+----------------------+--------------------------------------------------+

無事にテーブルが作成されました!✨✨

もし、上手く作成されない場合は、
migrationファイルやentityファイルの読み込みが上手くいっていないかもしれません。
ormconfigの中でentitiesやmigrationsをdistファイルから読み込むように指定しています。
そのため一度、distファイルを削除して(yarn run startした際に再度作成されるので、心配無用です!)
もう一度yarn run startでアプリケーションを起動してください!

その際に、distファイルの中にもentitymigrationが作成されているか確認を忘れずにd( ̄  ̄)

なお、 マイグレーションの状態確認やリバーとは下記のコマンドでできますよ( ^∀^)

// マイグレーションの状態確認
yarn ts-node node_modules/.bin/typeorm migration:show
// マイグレーションのrevert
yarn ts-node node_modules/.bin/typeorm migration:revert

tree

今回修正した場所を明記しています

※一部抜粋
admin-app
├── README.md
├── dist
│   ├── ormconfig.d.ts
│   ├── ormconfig.js
│   ├── ormconfig.js.map
│   ├── src
│   │   └── typeorm←これ追加されてる(自動で)
│   │       ├── entity←これ追加されてる(自動で)
│   │       │   ├── admin_info.entity.d.ts
│   │       │   ├── admin_info.entity.js
│   │       │   └── admin_info.entity.js.map
│   │       └── migration←これ追加されてる(自動で)
│   │           ├── 1643988029988-init.d.ts
│   │           ├── 1643988029988-init.js
│   │           └── 1643988029988-init.js.map
│   └── tsconfig.build.tsbuildinfo
├── nest-cli.json
├── node_modules
├── ormconfig.ts←これ追加する
├── package.json
├── src
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts←この中にtypeorm設定追記する
│   ├── app.service.ts
│   ├── main.ts
│   └── typeorm←これ追加する
│       ├── entity←これ追加する
│       │   └── admin_info.entity.ts←これ追加する
│       └── migration←これ追加する
│           └── 1643988029988-init.ts←これ追加されてる(自動で)
├── test
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock

p.s.
思ったよりも、スムーズに作成できた。
でも、Nest.jsの公式サイト見ると、他にも設定方法などがありそう。
もっと簡単な方法やスタイリッシュな書き方わかる人、ご教授いただきたいです。。。m(_ _)m
それにしても、Nest.jsのサイト英語ばっかりで、読むのつらみ、、、

. . .
次は、controllerやserviceの実装に入っていくっ!

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