基本的に自分用メモです.
DBの準備
今回はmysqlを使います.
予め適当なデータベースとユーザを作成して権限付与までしておきます.テーブルはまだ作らなくてOKです.
CREATE DATABASE testdb;
CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON testdb.* TO 'testuser'@'localhost';
NestJSのプロジェクト作成
NestJSのプロジェクトを作成して簡単な動作確認まで行います.
細かいところは公式ドキュメントを参照: https://docs.nestjs.com
npm i -g @nestjs/cli
nest new nest-typeorm-handson // とりあえずnpm選択して進めます
nest g module user
nest g controller user
nest g service user
これでnest-typeorm-handson以下にこんな感じにファイルが生成されます.
src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
└── user
├── user.controller.spec.ts
├── user.controller.ts
└── user.module.ts
最低限の動作の追加
UserServiceに以下を追加します
sample(): string {
return 'UserService';
}
UserControllerに以下のコンストラクタとメソッドを追加します.
constructor(private readonly service: UserService) {}
@Get()
get() {
return this.service.sample();
}
npm run start
で起動し,ブラウザでlocalhost:3000/user
にアクセスするとUserServiceの文字が出るはずです.
これで準備完了です.
TypeORMを使ってDB接続する
ここからTypeORMの出番です.
まずは準備します.
npm install --save @nestjs/typeorm typeorm mysql
そしてAppModuleの@Moduleの中身のimportsを以下のように書き換えます
imports: [
UserModule, // UserModuleはもともと追加されています
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'testuser',
password: 'password',
database: 'testdb',
entities: [],
synchronize: false,
})
],
さて,ここでnpm run start
します.
すると以下のようなエラーが出る場合があります
[Nest] 70420 - 2020-09-11 22:23:00 [TypeOrmModule] Unable to connect to the database. Retrying (1)... +8ms
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
at Handshake.Sequence._packetToError (/Users/home/nest-typeorm-handson/node_modules/mysql/lib/protocol/sequences/Sequence.js:47:14)
これはユーザの設定関連が原因なのでmysqlで以下を実行すると治ります.
ALTER USER 'testuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
次にEntityを作ります.src/user/user.entity.tsを作成し,以下のように作ります.
import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity()
export class User {
@PrimaryColumn({ length: 255 })
id: string;
@Column({ length: 255 })
name: string;
@Column()
age: number;
}
さらにAppModuleに先ほど書いたDBの接続情報にこのEntityを使うことを教えてあげます.
TypeOrmModule.forRoot({
// 一部省略
database: 'testdb',
entities: [User], // <-追加
})
UserModuleには以下を追加します.
imports: [TypeOrmModule.forFeature([User])],
そして,Repositoryの準備です.UserServiceを以下のように書き換えます.コピペでOKです.
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { User } from "./user.entity";
import { Repository } from "typeorm";
@Injectable()
export class UserService {
constructor(@InjectRepository(User) private readonly repository: Repository<User>) {}
sample(): Promise<Array<User>> {
return this.repository.find();
}
}
さて,ここでnpm run start
してlocalhost:3000/user
にアクセスするとエラーが出ます.
エラー内容はER_NO_SUCH_TABLE: Table 'testdb.user' doesn't exist
です.そりゃあそうですね,テーブルまだ作って無いですから.
マイグレーション機能でテーブルを作る
EntityなどからDDLを生成することができます.
そのために一旦先ほども書いたDBの接続情報を以下のように./ormconfig.tsにも書きます.
module.exports = {
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'testuser',
password: 'password',
database: 'testdb',
entities: ['src/**/*.entity.ts'],
migrations: ['db/migrations/*.ts'],
synchronize: false,
cli: {
migrationsDir: 'db/migrations'
}
}
そしてpackage.jsonのscriptsに以下を追加します
"typeorm": "ts-node ./node_modules/.bin/typeorm --config ormconfig.ts"
npm run typeorm -- migration:generate -n Initialize
すると./db/migrationsに'数列-Initialize.ts'というファイルが生成され,中にはDDLが書かれていることがわかります.
そして,以下のコマンドを実行するとテーブルが作成されます
npm run typeorm migration:run
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| migrations |
| user |
+------------------+
そして再度npm run start
すると起動できます
(もしかするとエラーが出るかもしれませんが,AppModuleのprovidersにUserServiceが指定されていたら消してください.自分の環境ではそれで治りました)
これで接続完了です.テーブルに適当にinsertしてからlocalhost:3000/user
にアクセスするとinsertした内容が出力されるはずです.