使用 Node 操作数据库,可选择的 ORM 库有 TypeORM、Sequelize 等,这里选用 Sequelize-Typescript。
下面以一个 user 模块为例,展示使用方法,该模块的结构如下:
--module
--user
--user.controller.ts
--user.model.ts
--user.service.ts
--user.module.ts
安装依赖
yarn add @nestjs/sequelize sequelize sequelize-typescript mysql2
yarn add @types/sequelize -D
定义模型
// user.model.ts
import { Column, Length, Model, Table, DataType } from 'sequelize-typescript'
@Table({ tableName: 'User' })
export class User extends Model<User> {
@Column({ comment: '自增 ID', autoIncrement: true, primaryKey: true })
id: number
@Length({ min: 3, max: 32 })
@Column({ comment: '姓名', type: DataType.STRING(32) })
name: string
@Column({ comment: '是否删除', defaultValue: false })
_delete: boolean
}
导入模块
// app.module.ts
import { Module } from '@nestjs/common'
import { SequelizeModule } from '@nestjs/sequelize'
@Module({
imports: [
SequelizeModule.forRoot({
dialect: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'test',
autoLoadModels: true, // 自动载入模型
synchronize: true // 同步自动载入的模型
}),
],
})
export class AppModule {}
实现 Service
在 service 中使用 model 操作数据库
import { Injectable } from '@nestjs/common'
import { InjectModel } from '@nestjs/sequelize'
import { Sequelize } from 'sequelize-typescript'
import { User } from './user.model'
@Injectable()
export class UserService {
constructor(
@InjectModel(User)
private readonly userModel: typeof User
) {}
async getOne(id: number) {
const item = await this.userModel.findByPk(id)
return item
}
}
实现 Controller
import { Controller, Get, Param } from '@nestjs/common'
import { UserService } from './user.service'
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get('/:id')
async getOne(@Param('id') id: number) {
return this.userService.getOne(id)
}
}
实现 Module
import { Module } from '@nestjs/common'
import { SequelizeModule } from '@nestjs/sequelize'
import { User } from './user.model'
import { UserController } from './user.controller'
import { UserService } from './user.service'
@Module({
imports: [SequelizeModule.forFeature([User])],
providers: [UserService],
controllers: [UserController]
})
export class UserModule {}
参数配置
经过上面的步骤,一个使用 musql 数据库的简单模块就实现了,但是数据库参数配置硬编码在代码里面,并不是一个好的方案,这里通过 @nestjs/config 提供的配置能力,实现运行时参数注入。
首先,在项目根目录下创建 .env 文件
# .env
# MYSQL
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USERNAME=root
MYSQL_PASSWORD=root
MYSQL_DATABASE=test
接下来,实现数据库模块
// module/database/index.ts
import { SequelizeModule } from '@nestjs/sequelize'
import { ConfigModule, ConfigService } from '@nestjs/config'
export default [
SequelizeModule.forRootAsync({ // 注意,为了使用 ConfigModule,请使用 forRootAsync 方法
imports: [ConfigModule],
useFactory: (configService: ConfigService) => {
return {
dialect: 'mysql',
host: configService.get('MYSQL_HOST'),
port: configService.get('MYSQL_PORT'),
username: configService.get('MYSQL_USERNAME'),
password: configService.get('MYSQL_PASSWORD'),
database: configService.get('MYSQL_DATABASE'),
autoLoadModels: true,
synchronize: true
}
},
inject: [ConfigService]
})
]
接下来,在根模块下引入配置模块
// app.module.ts
import { APP_FILTER } from '@nestjs/core'
import { Module } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'
import { UserModule } from './module/user/user.module'
import databaseModule from './module/database'
@Module({
providers: [
{
provide: APP_FILTER,
useClass: ExceptionFilter
}
],
imports: [
UserModule,
ConfigModule.forRoot(),
databaseModule
]
})
export class AppModule {}