五、数据库连接(nestjs+next.js从零开始一步一步创建通用后台管理系统)

485 阅读1分钟

TypeORM 支持许多关系型数据库,例如 PostgreSQL、Oracle、Microsoft SQL Server、SQLite,甚至包括 NoSQL 数据库如 MongoDB。而最新的prisma支持的数据库种类还比较少,所以选用TypeORM。

1、安装依赖

pnpm install --save @nestjs/typeorm@10.0.2 typeorm mysql2

注意需要使用10版本的@nestjs/typeorm,如果使用最新11版本会报错。

2、配置连接参数

在app.module.ts文件中增加TypeOrmModule.forRootAsync的配置参数,数据库连接参数使用了环境变量。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';

import { TestModule } from './test/test.module';
import { CoreModule } from './core/core.module';

//定义环境变量文件名
const envFilePath = [`.env.${process.env.NODE_ENV || 'development'}`,'.env'];

@Module({
  imports: [
    //配置使用环境变量,其中envFilePath支持同时加载多个文件,文件的顺序决定了文件的加载顺序,从后到前加载
    //多个配置文件的内容会组合到一起,后加载的配置文件的配置项会覆盖先加载的
    ConfigModule.forRoot({
      envFilePath,
      isGlobal: true,//配置为全局模块,在其他模块中使用就不用导入了
      //配置项验证
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test')
          .default('development'),
        //db_port: Joi.number().default(3000).valid(3000, 3001, 3002)
        // 可以添加更多验证规则
      }),  
    }),
    //配置数据库连接参数
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => {
        return {
          type: 'mysql',
          host: config.get<string>('MYSQL_HOST'),
          port: config.get<number>('MYSQL_PORT'),
          username: config.get<string>('MYSQL_USER'),
          password: config.get<string>('MYSQL_PASSWORD'),
          database: config.get<string>('MYSQL_DATABASE'),
          entities: [__dirname + '/**/*.entity{.ts,.js}'],
          charset: 'utf8mb4',
          autoLoadEntities: true,//设置自动加载实体
          // 生产环境中禁止开启,应该使用数据迁移,否则数据会被覆盖
          synchronize: true,
        };
      },
    }),
    TestModule,  
    CoreModule,
],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

环境变量配置如下:

//.env
# 数据库配置
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=root
MYSQL_DATABASE=test

3、配置数据库实体

修改test.entity.ts代码如下,entity是数据库表对应的实体类,注意需要@Entity注解。

import { ApiProperty } from "@nestjs/swagger";
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; 
//注解指定数据库表名
@Entity("test")
export class TestEntity {
  //自动生成的主键
  @PrimaryGeneratedColumn()
  id: number;
  //swagger接口说明
  @ApiProperty({
    example: "admin",
    description: "用户名",
  })
  //指定是数据表的一个列,如果不加该注解,则表不创建该字段
  @Column()
  username: string;

  @ApiProperty({
    example: "123456",
    description: "密码",
  })
  @Column()
  password: string;
  //该列有一个默认值
  @Column({ default: true })
  isActive: boolean;
}

配置表单传输对象dto

//create-test.dto.ts
import { ApiProperty } from "@nestjs/swagger";
export class CreateTestDto {
  @ApiProperty({
    example: "admin",
    description: "用户名称",
  })
  userName: string;

  @ApiProperty({
    example: "123456",
    description: "测试密码",
  })
  password: string;
}

4、在模块中使用

在模块中使用时需要先在模块中导入该实体类,或者在使用时无法生成repository。

//test.module.ts

import { Module } from '@nestjs/common';
import { TestService } from './test.service';
import { TestController } from './test.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TestEntity } from './entities/test.entity';

@Module({
  controllers: [TestController],
  providers: [TestService],
  imports: [TypeOrmModule.forFeature([TestEntity])],
})
export class TestModule {}

在使用数据库的地方注入该实体:

//test.service.ts
import { Injectable } from '@nestjs/common';
import { CreateTestDto } from './dto/create-test.dto';
import { UpdateTestDto } from './dto/update-test.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TestEntity } from './entities/test.entity';

@Injectable()
export class TestService {
  constructor(
    //使用注解注入Repository
    @InjectRepository(TestEntity)
    private testRepository: Repository<TestEntity>,
  ){}

  create(createTestDto: CreateTestDto) {
    this.testRepository.save(createTestDto);
    return '保存成功';
  }

  findAll() {
    const data=this.testRepository.find();
    return data;
  }

  findOne(id: number) {
    return `This action returns a #${id} test`;
  }

  update(id: number, updateTestDto: UpdateTestDto) {
    return `This action updates a #${id} test`;
  }

  remove(id: number) {
    return `This action removes a #${id} test`;
  }
}

5、测试

新增记录:

2025-05-15-16-42-32-image.png

使用数据库查看工具可以看到数据库中已经多了一条数据:

2025-05-15-16-46-33-image.png

查询记录:

2025-05-15-16-47-20-image.png