如何用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
相关产品推荐
相关产品推荐

