求助:在NestJS(TypeORM)中创建表时自动生成首行数据的方法
在NestJS中使用TypeORM自动插入首行初始化数据的实现方案
下面是几种实用的实现方式,根据你的场景选择即可:
方式一:利用TypeORM数据种子(Seeding)
这是TypeORM官方推荐的批量数据初始化方案,适合需要管理多组初始化数据的场景。
- 创建种子文件
在项目中新建种子目录(比如src/seeds),编写初始化数据的种子类:
// src/seeds/initial-admin.seed.ts import { DataSource } from 'typeorm'; import { Seeder } from 'typeorm-extension'; import { Admin } from '../entities/admin.entity'; export class InitialAdminSeeder implements Seeder { async run(dataSource: DataSource): Promise<void> { const adminRepository = dataSource.getRepository(Admin); // 检查是否已存在初始化数据 const existingAdmin = await adminRepository.findOneBy({ username: 'admin' }); if (!existingAdmin) { const admin = adminRepository.create({ username: 'admin', password: 'hashed_password_here', // 注意要提前加密密码 email: 'admin@example.com' }); await adminRepository.save(admin); } } }
- 配置TypeORM种子路径
在app.module.ts的TypeORM配置中添加种子相关配置:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; import { InitialAdminSeeder } from './seeds/initial-admin.seed'; @Module({ imports: [ ConfigModule.forRoot(), TypeOrmModule.forRoot({ type: 'mysql', host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT), username: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, // 生产环境建议关闭,改用迁移 seeds: [InitialAdminSeeder], }), ], }) export class AppModule {}
- 运行种子命令
在package.json中添加脚本:
{ "scripts": { "seed:run": "typeorm-extension seed:run -d dist/src/data-source.js" } }
执行npm run seed:run即可触发数据插入。如果希望应用启动时自动执行,可以在main.ts中手动调用种子逻辑。
方式二:应用启动时自动初始化(适合简单首行数据)
如果只需要插入单条初始化数据,直接在应用启动阶段执行更简便:
- 创建初始化服务
// src/services/initial-data.service.ts import { Injectable, OnApplicationInit } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Setting } from '../entities/setting.entity'; @Injectable() export class InitialDataService implements OnApplicationInit { constructor( @InjectRepository(Setting) private settingRepository: Repository<Setting>, ) {} async onApplicationInit() { // 检查是否已有配置数据 const hasSetting = await this.settingRepository.exists(); if (!hasSetting) { const defaultSetting = this.settingRepository.create({ siteName: '我的NestJS站点', siteDesc: '这是自动初始化的站点配置', isEnabled: true, }); await this.settingRepository.save(defaultSetting); console.log('默认站点配置已初始化'); } } }
- 在模块中注册服务
确保该服务被注入到模块中,NestJS会在应用启动时自动执行onApplicationInit方法:
// src/app.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Setting } from './entities/setting.entity'; import { InitialDataService } from './services/initial-data.service'; @Module({ imports: [TypeOrmModule.forFeature([Setting])], providers: [InitialDataService], }) export class AppModule {}
方式三:通过迁移文件插入数据
如果项目使用TypeORM迁移来管理数据库结构,可以在创建表的迁移文件中直接添加插入语句:
// src/migrations/1690000000000-CreateSettingTable.ts import { MigrationInterface, QueryRunner } from 'typeorm'; export class CreateSettingTable1690000000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { // 创建表 await queryRunner.query(` CREATE TABLE \`setting\` ( \`id\` int NOT NULL AUTO_INCREMENT, \`siteName\` varchar(255) NOT NULL, \`siteDesc\` text NULL, \`isEnabled\` tinyint NOT NULL DEFAULT 1, PRIMARY KEY (\`id\`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; `); // 插入初始化数据 await queryRunner.query(` INSERT INTO \`setting\` (\`siteName\`, \`siteDesc\`) VALUES ('我的NestJS站点', '这是自动初始化的站点配置'); `); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`DROP TABLE \`setting\``); } }
运行npm run migration:run时,创建表的同时会自动插入这条初始化数据。
内容的提问来源于stack exchange,提问作者HARI KRISHNAN
相关产品推荐
相关产品推荐

