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

NestJS结合Prisma如何编写匹配一对多关联类型的DTO

问题1:是否可以编写和Prisma自动生成类型完全匹配的DTO?

可以,但通常不建议直接将对外暴露的API DTO和Prisma内部类型完全对齐:

  • 手动编写的场景下,你需要完全复刻Prisma生成的嵌套输入类型结构,包括create/connect/connectOrCreate等操作字段,同时要适配Prisma的Enumerable(支持单个值或数组)、XOR等工具类型的约束,代码冗余度高、维护成本大。
  • 也可以使用prisma-nestjs-dto-generator这类开源工具,直接根据你的Prisma Schema生成匹配的DTO类,不需要手动编写。
  • 对外API DTO如果完全对齐Prisma内部类型,会把数据库操作的细节暴露给前端,增加安全风险,也会让前端接口调用逻辑和Prisma的实现强绑定,不利于后续迭代。

问题2:如何调整orderable_bundle的DTO,为嵌套的orderable_test字段添加create包装层?

有两种常见的实现方案,你可以根据业务需求选择:

方案1:DTO直接对齐Prisma创建格式

直接修改DTO结构匹配Prisma要求的嵌套创建格式,参数可以直接传给Prisma的create方法无需额外转换:

// 去掉orderable_bundleId的测试创建DTO,创建关联时该字段会由Prisma自动维护
class OrderableTestCreateDTO {
    @ApiProperty()
    test_name: string;
    @ApiProperty()
    test_id: number;
    @ApiProperty()
    price: number;
    @ApiProperty()
    is_orderable: boolean;
    @ApiProperty()
    is_active: boolean;
}

// 嵌套测试创建的输入DTO,匹配Prisma的嵌套操作结构
class OrderableTestNestedInputDTO {
    @ApiPropertyOptional({ type: [OrderableTestCreateDTO] })
    create?: OrderableTestCreateDTO[];

    // 如果需要支持关联已有的测试,还可以补充connect等字段
    // @ApiPropertyOptional({ type: [Number] })
    // connect?: {id: number}[];
}

// 调整后的套餐DTO
class OrderableBundleDTO {
    @ApiProperty()
    bundle_name: string;
    @ApiProperty()
    bundle_id: number;
    @ApiProperty()
    price: number;
    @ApiProperty()
    is_orderable: boolean;
    @ApiProperty()
    is_active: boolean;
    @ApiPropertyOptional({ type: () => OrderableTestNestedInputDTO })
    orderable_tests?: OrderableTestNestedInputDTO;
}

方案2:对外DTO保持简洁,Service层做格式转换

如果不希望前端感知Prisma的内部格式,前端传参直接传测试数组即可,你可以在Service层手动包装create层:
首先对外的套餐DTO调整为数组类型(一个套餐对应多个测试):

class OrderableBundleDTO {
    @ApiProperty()
    bundle_name: string;
    @ApiProperty()
    bundle_id: number;
    @ApiProperty()
    price: number;
    @ApiProperty()
    is_orderable: boolean;
    @ApiProperty()
    is_active: boolean;
    @ApiPropertyOptional({ type: [OrderableTestDTO] })
    orderable_tests?: OrderableTestDTO[];
}

然后在Service的创建逻辑里手动添加create层:

async createBundle(dto: OrderableBundleDTO) {
  const { orderable_tests, ...bundleData } = dto;
  return this.prisma.orderable_bundle.create({
    data: {
      ...bundleData,
      // 存在测试数据时自动包装create层
      ...(orderable_tests?.length && {
        orderable_tests: {
          create: orderable_tests.map(test => {
            // 过滤掉不需要的关联ID字段
            const { orderable_bundleId, ...testData } = test;
            return testData;
          })
        }
      })
    }
  })
}

这种方案对外接口更友好,和Prisma实现解耦,更推荐业务系统使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:24:03