You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在NestJS中结合MySQL实现自定义自动生成ID功能

在NestJS结合MySQL实现自定义格式自动生成ID

要生成如GM22JA001格式的ID(规则:固定公司标识+年份后2位+月份两位缩写+三位补零自增编号),可以通过数据库序列表+NestJS事务逻辑实现,确保并发场景下ID不重复,以下是具体实现方案:

1. 数据库表设计

创建专门的序列维护表,用于按「公司标识+年月」跟踪当前自增编号,避免全表扫描目标表的性能问题:

CREATE TABLE `id_generator` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `company_code` VARCHAR(2) NOT NULL COMMENT '固定公司标识,如GM',
  `year_month` VARCHAR(4) NOT NULL COMMENT '年份后2位+月份缩写,如22JA',
  `current_seq` INT NOT NULL DEFAULT 0 COMMENT '当前自增序列值',
  UNIQUE KEY `uk_company_yearmonth` (`company_code`, `year_month`)
);

2. 定义TypeORM实体

创建IdGenerator实体映射上述表:

import { Entity, Column, PrimaryGeneratedColumn, Unique } from 'typeorm';

@Entity('id_generator')
@Unique(['companyCode', 'yearMonth'])
export class IdGenerator {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ name: 'company_code', length: 2 })
  companyCode: string;

  @Column({ name: 'year_month', length: 4 })
  yearMonth: string;

  @Column({ name: 'current_seq' })
  currentSeq: number;
}

3. 实现ID生成服务

创建NestJS服务,通过数据库事务保证序列更新的原子性,处理并发场景:

import { Injectable, Logger } from '@nestjs/common';
import { EntityManager, Repository } from 'typeorm';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { IdGenerator } from './entities/id-generator.entity';

@Injectable()
export class CustomIdGeneratorService {
  private readonly logger = new Logger(CustomIdGeneratorService.name);
  // 自定义月份两位缩写,对应1-12月
  private readonly MONTH_ABBR = ['JA', 'FE', 'MR', 'AP', 'MY', 'JN', 'JL', 'AU', 'SE', 'OC', 'NV', 'DE'];
  // 公司标识可移至.env配置
  private readonly COMPANY_CODE = 'GM';

  constructor(
    @InjectRepository(IdGenerator)
    private readonly idGeneratorRepo: Repository<IdGenerator>,
    @InjectEntityManager()
    private readonly entityManager: EntityManager,
  ) {}

  async generateCustomId(): Promise<string> {
    const now = new Date();
    const yearSuffix = now.getFullYear().toString().slice(-2);
    const monthAbbr = this.MONTH_ABBR[now.getMonth()];
    const yearMonthKey = `${yearSuffix}${monthAbbr}`;

    // 用事务确保序列更新原子性
    return await this.entityManager.transaction(async (txEntityManager) => {
      // 查询当前公司+年月的序列记录
      let generatorRecord = await txEntityManager.findOne(IdGenerator, {
        where: {
          companyCode: this.COMPANY_CODE,
          yearMonth: yearMonthKey,
        },
      });

      if (!generatorRecord) {
        // 首次生成当月ID,初始化序列为1
        generatorRecord = txEntityManager.create(IdGenerator, {
          companyCode: this.COMPANY_CODE,
          yearMonth: yearMonthKey,
          currentSeq: 1,
        });
        await txEntityManager.save(generatorRecord);
      } else {
        // 已有记录,序列自增
        generatorRecord.currentSeq += 1;
        await txEntityManager.save(generatorRecord);
      }

      // 格式化三位序列为补零字符串
      const seqStr = generatorRecord.currentSeq.toString().padStart(3, '0');
      return `${this.COMPANY_CODE}${yearMonthKey}${seqStr}`;
    });
  }
}

4. 在业务逻辑中调用ID生成服务

比如在创建业务实体(如商品)时,调用生成服务获取自定义ID:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Product } from './entities/product.entity';
import { CustomIdGeneratorService } from '../custom-id-generator/custom-id-generator.service';

@Injectable()
export class ProductService {
  constructor(
    @InjectRepository(Product)
    private readonly productRepo: Repository<Product>,
    private readonly idGeneratorService: CustomIdGeneratorService,
  ) {}

  async createProduct(productData: Partial<Product>) {
    const customId = await this.idGeneratorService.generateCustomId();
    const product = this.productRepo.create({
      ...productData,
      customId, // 赋值自定义ID
    });
    return await this.productRepo.save(product);
  }
}

关键说明

  • 并发安全:通过数据库事务包裹查询+更新操作,确保同一时刻只有一个请求能修改序列值,避免重复ID。
  • 扩展性:公司标识可移至环境变量(如process.env.COMPANY_CODE),支持多公司场景;月份缩写可根据需求调整。
  • 性能优化:使用独立的序列表而非查询目标表最大ID,避免大表全表扫描,提升生成效率。

内容的提问来源于stack exchange,提问作者Jothi Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:50:45