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

如何用TypeORM安全插入关联表数据并实现事务回滚?求代码示例

使用TypeORM安全插入关联数据并实现事务回滚

必须使用TypeORM的事务来实现数据一致性保障——因为涉及多表关联插入,只要任一环节出错,所有已插入的数据都需要回滚,避免出现孤立的Order或Sample数据。以下是完整的实现方案:

1. 实体关联定义

首先确保三个实体的关联关系配置正确:

Order 实体

import { Entity, PrimaryGeneratedColumn, Column, OneToMany, CreateDateColumn } from "typeorm";
import { Sample } from "./Sample";

@Entity()
export class Order {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  date: string; // 可根据需求改为Date类型

  @OneToMany(() => Sample, sample => sample.order)
  samples: Sample[];

  @CreateDateColumn()
  createdAt: Date;
}

Patient 实体

import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Sample } from "./Sample";

@Entity()
export class Patient {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string; // 其他患者字段可按需添加

  @OneToMany(() => Sample, sample => sample.patient)
  samples: Sample[];
}

Sample 实体

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { Order } from "./Order";
import { Patient } from "./Patient";

@Entity()
export class Sample {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @ManyToOne(() => Order, order => order.samples, { onDelete: "CASCADE" })
  order: Order;

  @ManyToOne(() => Patient, patient => patient.samples, { onDelete: "CASCADE" })
  patient: Patient;
}

2. 事务实现代码示例

使用TypeORM的transaction方法自动处理提交与回滚逻辑,所有操作都在事务管理器中执行:

import { getManager } from "typeorm";
import { Order } from "./entities/Order";
import { Sample } from "./entities/Sample";
import { Patient } from "./entities/Patient";

// 处理创建Order的POST请求核心逻辑
async function createOrder(requestData: { 
  date: string; 
  samples: Array<{ patientId: number; name: string }> 
}) {
  const entityManager = getManager();

  try {
    // 启动事务:回调内所有操作要么全部成功提交,要么异常时全部回滚
    await entityManager.transaction(async (txManager) => {
      // 1. 创建并保存Order
      const newOrder = txManager.create(Order, { date: requestData.date });
      const savedOrder = await txManager.save(newOrder);

      // 2. 批量处理样本,先验证患者存在性
      const samplesToSave: Sample[] = [];
      for (const sampleItem of requestData.samples) {
        // 验证患者存在,不存在则抛出异常触发回滚
        const targetPatient = await txManager.findOne(Patient, {
          where: { id: sampleItem.patientId }
        });
        if (!targetPatient) {
          throw new Error(`ID为${sampleItem.patientId}的患者不存在`);
        }

        const newSample = txManager.create(Sample, {
          name: sampleItem.name,
          order: savedOrder,
          patient: targetPatient
        });
        samplesToSave.push(newSample);
      }

      // 3. 批量保存样本
      await txManager.save(samplesToSave);
    });

    return { success: true, msg: "订单及样本创建成功" };
  } catch (err) {
    // 事务已自动回滚,此处返回错误信息
    return { success: false, msg: (err as Error).message };
  }
}

3. 关键注意事项

  • 必须使用事务管理器txManager执行所有数据库操作,确保所有操作处于同一事务上下文。
  • 提前验证关联数据(如Patient存在性),避免插入无效关联数据,异常会直接触发事务回滚。
  • 批量保存样本比逐个保存更高效,同时减少事务内的数据库交互次数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:20:34