NestJSでREST(その2)
前回まで
NestJSのCLIでWebサーバー部分はできちゃいました。👏
データベースと繋ぐ
TypeORM(とPostgres)を導入
本家を含めて、mysqlが多いような気がしますが、今回は、別件でPostgesを使っていたので、Postgresでやります。
$ npm install --save @nestjs/typeorm typeorm pg
customersを実装する
まず、テーブルを作ります。
CREATE TABLE CUSTOMER (
CUSTOMER_ID int,
NAME text,
ADDRESS text,
CONSTRAINT PK_CUSTOMER PRIMARY KEY(CUSTOMER_ID)
);
ここで英大文字で書いても、Postgresさんは英小文字で認識されていて、後でハマります。
TypeORMの設定
TypeORMにデータベースの設定をしつつ、NestJSのモジュールとしてAppModuleに組み込みます。
@@ -1,10 +1,25 @@
import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomersModule } from './customers/customers.module';
+import { Customer } from './customers/entities/customer.entity';
@Module({
- imports: [CustomersModule],
+ imports: [
+ CustomersModule,
+ TypeOrmModule.forRoot({
+ type: 'postgres',
+ host: '■■■■',
+ port: 5432,
+ username: '■■■■',
+ password: '■■■■',
+ database: 'postgres',
+ entities: [Customer],
+ logging: true,
+ synchronize: false,
+ }),
+ ],
controllers: [AppController],
providers: [AppService],
})
loggingをtrueにしておくとハマったときに助かります。(ハマってからtrueにしました)
設定がこんな感じだと丸見えなので、あとでなんとかします。
エンティティの設定
Java界隈でお馴染みの香りがします。
@@ -1 +1,13 @@
-export class Customer {}
+import { Entity, Column, PrimaryColumn } from 'typeorm';
+
+@Entity()
+export class Customer {
+ @PrimaryColumn({ name: 'customer_id' })
+ customerId: number;
+
+ @Column()
+ name: string;
+
+ @Column()
+ address: string;
+}
ここでハマりました。TypeORMさんは、テーブル名やカラム名をダブルクォートで囲んで渡してます。SQLの世界では大文字小文字の区別はしないのですが、Postgresさんは、ダブルクォートで囲むと書かれたとおりの文字列としてマッチングするそうです。
ですから、上で、@PrimaryColumn({ name: 'customer_id' })としているところをCREATE TABLE文のとおりに'CUSTOMER_ID'としてしまうと、「そんなカラムはありません」の一点張りで動きません。
今回に限らず、実は、ORマッパー嫌いです(笑)。今回は、logging: trueにして、TypeORMが表示したSQLを直叩きしないと解決できませんでした。「な。だから最初から俺にSQL書かせろよ」
DTOの設定
前回のイメージのJSONになるように定義します。
@@ -1 +1,5 @@
-export class CreateCustomerDto {}
+export class CreateCustomerDto {
+ customerId: number;
+ name: string;
+ address: string;
+}
Update用のクラスは、以下のように、生成された状態のまま変更しなくても大丈夫です。
export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {}
PartialTypeって何?ってなりますよね。
The PartialType() function returns a type (class) with all the properties of the input type set to optional.
むむむ。ということで、ソースコードを遡ると
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
ということで、?が付いてオプショナル。作成の時は全部だけど、更新の時は欠けてもいい。というのができるのね。TypeScriptは深い。
次回は
serviceからやります。
Discussion