TypeORM事务中如何将实体全部列传递给EntitySubscriberInterface?更新订阅者无法获取完整实体列的技术问询
我之前也遇到过类似的问题,TypeORM在处理QueryBuilder的批量更新时,订阅者的event.entity确实只会包含你在set()里指定的字段——哪怕你用了returning("*")。这是因为QueryBuilder的更新操作不像save()方法那样基于完整实体实例,TypeORM不会自动把返回的所有字段映射到event.entity中,但别担心,我们有几种实用的方法可以拿到完整的数据:
方法1:直接使用event.raw获取完整返回结果
当你在QueryBuilder中使用returning("*")时,数据库返回的所有列都会被存储在event.raw属性里。如果是批量更新,event.raw会是一个数组,每个元素对应一行更新后的完整数据。
修改你的订阅者代码如下:
async afterUpdate(event: UpdateEvent<Booking>): Promise<void> { // 封装单个Booking的处理逻辑 const processBooking = async (rawBooking: any) => { if (rawBooking.status === BookingStatus.BOOKED) { // rawBooking包含所有数据库列,比如booking_uuid、status、editor、updated_at等 console.log("完整的Booking数据:", rawBooking); // 直接用rawBooking里的字段执行后续业务逻辑 const bookingUuid = rawBooking.booking_uuid; // 注意数据库列名可能是下划线格式 // ... 你的后续业务操作代码 } }; if (Array.isArray(event.raw)) { // 处理批量更新,并行处理所有返回行 await Promise.all(event.raw.map(processBooking)); } else { // 处理单个更新的情况 await processBooking(event.raw); } }
方法2:通过queryRunner在事务内查询完整实体
如果你需要操作TypeORM的实体实例而不是原始数据库数据,可以利用event.queryRunner(它属于当前事务的连接)来查询完整的Booking实体。这样能保证你拿到的是事务内最新的数据,不会有隔离性问题:
async afterUpdate(event: UpdateEvent<Booking>): Promise<void> { const processBooking = async (rawBooking: any) => { if (rawBooking.status === BookingStatus.BOOKED) { // 用当前事务的queryRunner查询完整实体 const fullBooking = await event.queryRunner.manager.findOne(Booking, { where: { bookingUuid: rawBooking.booking_uuid } // 注意列名与实体属性的对应关系 }); if (fullBooking) { console.log("完整的Booking实体:", fullBooking); // 执行后续业务操作,比如调用关联服务、更新关联实体等 } } }; if (Array.isArray(event.raw)) { await Promise.all(event.raw.map(processBooking)); } else { await processBooking(event.raw); } }
为什么event.entity只有修改的字段?
这是TypeORM的设计行为:当使用QueryBuilder执行更新时,它不会自动构建完整的实体实例,只会把你在set()中明确指定的字段映射到event.entity里。而returning("*")的结果会直接存在event.raw中,这是数据库返回的原始数据,没有经过TypeORM的实体映射。
注意事项
- 要明确数据库列名和实体属性名的对应关系(比如PostgreSQL默认用下划线命名,实体用驼峰的话,
bookingUuid对应数据库的booking_uuid)。 - 因为更新操作是在事务中执行的,订阅者的
afterUpdate也会在同一个事务上下文里触发,所以用event.queryRunner查询的数据是事务内的最新状态。
内容的提问来源于stack exchange,提问作者Yusuf Yasin
相关产品推荐
相关产品推荐

