nestjsとSqliteで簡単なAPIを作る
NestJSで使用できるORMであるTypeORMから、SQLiteを利用してデータベースを作り、APIを公開してみる。参考にしたのは以下のリンク。
エンティティを作る
ここでは、id, name, descriptionというメンバを持つ簡単なエンティティItemを作成する。idは自動生成にするため、@PrimaryGeneratedColumn
デコレータを付ける。
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Item {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100 })
name: string;
@Column('text')
description: string;
}
サービスを作る
アプリケーションが実行されている間、データベースにアクセスするために、サービスを作る。サービスはAngularと同様@Injectable
デコレータを付けて定義する。
コンストラクタで引数にItemエンティティのリポジトリを与えている。この辺は定型のようなのでサンプルに倣って書く。
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Item } from './entities/item.entity';
@Injectable()
export class ItemService {
constructor( @InjectRepository( Item ) private readonly itemRepos: Repository<Item> ) {
}
async add( item: Item ): Promise<Item> {
let newItem = this.itemRepos.create( item );
return await this.itemRepos.save(newItem);
}
async findAll(): Promise<Item[]> {
return await this.itemRepos.find();
}
}
add
で使用しているcreate
メソッドは新しいエンティティを作るが、それだけではデータベースに保存されない。save
することでデータベースに保存されるので注意する。
コントローラを作る
作成したItemService
を外部から利用できるよう、リクエストを受け取ってサービスとやりとりをするコントローラを作る。
まず、コンストラクタではItemService
をInjectする。(Angularと同じ)
HTTPリクエストへの応答は、メソッドに@Get
, @Post
デコレータで対象のHTTPメソッドとルート(Route)指定することで定義する。戻り値はそのまま利用者に返されるオブジェクトになる。
メソッドには引数としてHTTPリクエストに含まれる情報を指定することができる。@Body(param)
を指定すれば、リクエストボディに含まれるparam
の値が引数で渡されるようになる。以下の例では、リクエストボディからname
とdescription
の値を取得し、新しいオブジェクトを作るのに使用している。
以下の例ではIDを自動生成するよう設定しているので、idの値にはundefinedを指定した。
import { Get, Post, Body, Controller } from '@nestjs/common';
@Controller()
export class ItemController {
constructor(private readonly itemService: ItemService) {}
@Get('/item')
findAll(): Promise<Item[]> {
return this.itemService.findAll()
}
@Post('/item')
add(
@Body('name') name: string,
@Body('description') description: string
): Promise<Item> {
return this.itemService.add( {id: undefined, name: name, description: description} );
}
}
追記 @Controller('ルート')にすれば、わざわざメソッドごとにルートを書かなくてよかった。
モジュールを作る
これは必須ではないが、機能ごとにモジュールを分けておくと良いらしい。サービスをproviders
、コントローラをcontrollers
、そしてエンティティをimports
内のforFeature( [ エンティティ ] )
に追加する。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [TypeOrmModule.forFeature([Item])],
providers: [ItemService],
controllers: [ItemController],
})
export class ItemModule {}
アプリケーションに組み込む
imports
の中に、使用するモジュールを列挙する。
データベースの本体として、TypeOrmModule.forRoot(オプション)
をインポートすれば、entitiesで指定した対象のエンティティに対して、そのデータベースが使用できるようになる。複数データベースの本体をインポートすることができるので、マスタデータやトランザクションデータでデータベースを使い分けることもできるらしい。
entitites
に文字列を追加すると、パターンマッチするファイルが公開するエンティティに対応するようになる。直接Item
としても良いので、楽な書き方を選べばよい。
entities
の指定を間違うと、以下の様なエラーが出てしまうので、その時は正しく指定できたか確認すること。
No repository for "Entity名" was found. Looks like this entity is not registered in current "default" connection
import { ItemModule } from './sample.service';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot( {
type: 'sqlite',
database: 'db/sqlitedb.db',
synchronize: true,
entities: [ 'src/entities/*.entity.ts' ]
} ), ItemModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
実行する
npm start
で実行後、何度か適当に'localhost:3000/item'にPOSTし、その後GETした結果、以下のようにPOSTしたItemが列挙された。
まとめ
以下を用意すれば、APIぽいものを作ることができることが分かった。LoopBack4よりシンプルで楽に書くことができてしまった。LoopBackのあのごちゃごちゃしたオマジナイデコレータは何だったのか…
- Itemエンティティを作る
- ItemサービスでItemエンティティを保存するリポジトリの操作を提供する
- ItemコントローラでItemサービスの提供する操作をAPIとして公開する
- Itemモジュールで上記3つをまとめる(optional)
- アプリケーションでItemエンティティを保持するデータベースとItemモジュールをインポートする
注意すること
デコレータが色々やってくれる分、見えない制約につまづく可能性があることが分かった。
サービスとしてリポジトリを作った際に、ItemServiceではなくItemRepositoryとしたところ、エラーもなくアプリケーションが起動しなくなってしまった。@InjectableRepository<Entity名>
にすると、勝手に〇〇Repositoryというクラスが作られ、うまくいかなくなるのかもしれない。特に目立ったエラーなく起動しない場合は、命名を見直す必要がありそう。
[nodemon] restarting due to changes...
[nodemon] starting `ts-node -r tsconfig-paths/register src/main.ts`
[Nest] 1228 - 2018-12-2 00:28:36 [NestFactory] Starting Nest application...
[Nest] 1228 - 2018-12-2 00:28:36 [InstanceLoader] TypeOrmModule dependencies initialized +135ms
[Nest] 1228 - 2018-12-2 00:28:36 [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 1228 - 2018-12-2 00:28:36 [InstanceLoader] TypeOrmCoreModule dependencies initialized +38ms
[Nest] 1228 - 2018-12-2 00:28:36 [InstanceLoader] TypeOrmModule dependencies initialized +1ms
[nodemon] clean exit - waiting for changes before restart
本来ならこの後で以下が続くはずなのに、勝手に止まってしまう。
[RouterResolver]
[RouterExplorer]
Author And Source
この問題について(nestjsとSqliteで簡単なAPIを作る), 我々は、より多くの情報をここで見つけました https://qiita.com/stm32p103/items/4cb0f352042cd856a12e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .