###### 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 {}
```