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

NestJS中解构JSON请求并分表存储数据的技术求助

解决NestJS中JSON数据分表存储的Service层实现问题

1. 先定义请求DTO(数据传输对象)

通过DTO规范请求数据结构,确保能正确解构输入:

// src/profile/dto/nutrient-item.dto.ts
export class NutrientItemDto {
  nutrient_id: number;
  quantity: number;
  unit: string;
}

// src/profile/dto/group.dto.ts
export class GroupDto {
  group_id: number;
  nutrients: NutrientItemDto[];
}

// src/profile/dto/create-profile.dto.ts
export class CreateProfileDto {
  title: string;
  groups: GroupDto[];
}

2. Service层核心实现

假设使用TypeORM操作数据库,以下是包含事务处理的Service层关键代码,保证数据一致性:

// src/profile/profile.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Profile } from './entities/profile.entity';
import { Nutrient } from './entities/nutrient.entity';
import { CreateProfileDto } from './dto/create-profile.dto';

@Injectable()
export class ProfileService {
  constructor(
    @InjectRepository(Profile)
    private profileRepository: Repository<Profile>,
    @InjectRepository(Nutrient)
    private nutrientRepository: Repository<Nutrient>,
  ) {}

  async create(createProfileDto: CreateProfileDto) {
    // 开启事务
    const queryRunner = this.profileRepository.manager.connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      // 1. 创建Profile记录,自动生成id和时间戳
      const profile = this.profileRepository.create({
        title: createProfileDto.title,
        // 若Profile实体未配置自动生成时间戳,手动添加:createdAt: new Date()
      });
      const savedProfile = await queryRunner.manager.save(profile);
      const profileId = savedProfile.id;

      // 2. 组装所有待插入的Nutrient数据
      const nutrientRecords: Partial<Nutrient>[] = [];
      createProfileDto.groups.forEach(group => {
        group.nutrients.forEach(nutrient => {
          nutrientRecords.push({
            profileId,
            groupId: group.group_id,
            nutrientId: nutrient.nutrient_id,
            quantity: nutrient.quantity,
            unit: nutrient.unit,
          });
        });
      });

      // 3. 批量插入Nutrient记录
      await queryRunner.manager.save(Nutrient, nutrientRecords);

      // 提交事务
      await queryRunner.commitTransaction();

      return { profile: savedProfile, nutrientsCount: nutrientRecords.length };
    } catch (error) {
      // 回滚事务
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      // 释放连接
      await queryRunner.release();
    }
  }
}

3. 补充说明

  • 实体结构要求:确保Profile实体包含id、title、createdAt字段;Nutrient实体包含profileId、groupId、nutrientId、quantity、unit字段。
  • 事务作用:避免出现Profile插入成功但Nutrients插入失败的情况,保证两张表的数据一致性。
  • 批量插入优势:相比逐条插入,批量操作能显著提升数据库处理效率,适合这类多关联数据的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:05:25