[前回][1]は、Nestjsのプロジェクトをダウンロードして、環境構築まで完了しました。
今回は、TypeOrmを使用して、データベースの作成〜接続までを行っていこうと思います!
[1]: [https://qiita.com/peach_s/items/a440fbd12120f2d822f4]
※Nest.js公式サイト(データベース編)
※[typeormの公式サイトはこちら][typeorm]
[typeorm]:[https://typeorm.io/#/]
##環境
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
のフォルダを作成し、さらにentity
とmigration
フォルダを追加。
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ファイルの中にもentity
やmigration
が作成されているか確認を忘れずに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の実装に入っていくっ!