###### tags: `NestJS` `typeORM` # Nestjs - TypeORM Intergration Nest提供`@nestjs/typeorm`套件來做TypeORM互動,因為TypeORM為TS中目前最成熟的ORM套件,他是用TS所寫的,所以能和Nest框架完美搭配。 以下會以MySQL為範例: 首先安裝套件: ```shell! $ npm install --save @nestjs/typeorm typeorm mysql2 ``` 安裝完後,將`TypeOrmModule`引入到`AppModule` ```typescript! import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'root', database: 'test', entities: [], synchronize: true, }), ], }) export class AppModule {} ``` :::warning Setting `synchronize: true` shouldn't be used in production - otherwise you can lose production data. ::: 當上面完成後,TypeORM的`DataSource`和`EntityManager`物件就可以在整個專案使用,如下: ```typescript! import { DataSource } from 'typeorm'; @Module({ imports: [TypeOrmModule.forRoot(), UsersModule], }) export class AppModule { constructor(private dataSource: DataSource) {} } ``` #### Repository pattern TypeORM 支援repository design pattern,所以各個entity都有其repository,這些repository可以從database data source取得。 以下建立`User` Entity做示範: ```typescript! import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() firstName: string; @Column() lastName: string; @Column({ default: true }) isActive: boolean; } ``` 為開始使用`User`Entity,我們將其放入app.module內的forRoot() method的entities陣列內。 ```typescript! import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './users/user.entity'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'root', database: 'test', entities: [User], synchronize: true, }), ], }) export class AppModule {} ``` 現在換看`UsersModule`: ```typescript! import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UsersService } from './users.service'; import { UsersController } from './users.controller'; import { User } from './user.entity'; @Module({ imports: [TypeOrmModule.forFeature([User])], providers: [UsersService], controllers: [UsersController], }) export class UsersModule {} ``` ** 以下方式與文件不同,而是將與資料庫互動的部分從service拆分出來為一個*.repository.ts,而後在service中注入repository進而拆分權責,以便維護。 ** /// 從這後開始修改 這個module使用`forFeature()`來定義是哪個repositories被註冊在目前的scope,有了這個,我們就可以將`UserRepository`使用`@InjectRepository()`注入到`UsersService`中,如下: ```typescript! import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { User } from './user.entity'; @Injectable() export class UsersService { constructor( @InjectRepository(User) private usersRepository: Repository<User>, ) {} findAll(): Promise<User[]> { return this.usersRepository.find(); } findOne(id: string): Promise<User> { return this.usersRepository.findOneBy({ id }); } async remove(id: string): Promise<void> { await this.usersRepository.delete(id); } } ``` 如果你想要在外部的module使用此repository,你一樣必須要到module這裡把import的`TypeOrmModule.forFeature`再把他export: ```typescript! import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './user.entity'; @Module({ imports: [TypeOrmModule.forFeature([User])], exports: [TypeOrmModule] }) export class UsersModule {} ```