使用 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 mysql2yarn add @types/sequelize -D
定义模型
// user.model.tsimport { 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.tsimport { 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# MYSQLMYSQL_HOST=localhostMYSQL_PORT=3306MYSQL_USERNAME=rootMYSQL_PASSWORD=rootMYSQL_DATABASE=test
接下来,实现数据库模块
// module/database/index.tsimport { 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.tsimport { 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 {}
