NestJS TypeORM Subscriber的afterUpdate事件无法返回更新列
解决TypeORM afterUpdate事件中updatedColumns为空的问题
为什么updatedColumns是空数组?
TypeORM的updatedColumns字段仅在通过实体管理器(EntityManager)或仓库(Repository)的save()方法更新实体实例时才会填充。如果使用QueryBuilder执行更新操作,TypeORM无法自动跟踪变更的列,因此updatedColumns会返回空数组。此外,若save()传入的实体与数据库中现有数据完全一致,updatedColumns也会是空数组。
获取更新列的可行方案
方案1:使用save()方法时直接读取updatedColumns
如果你的更新操作是通过repository.save(entity)或manager.save(entity)执行的,可直接从updatedColumns提取列名:
// 在订阅器的afterUpdate方法中 const updatedColumnNames = event.updatedColumns.map(col => col.propertyName); console.log('更新的列:', updatedColumnNames);
注意:确保更新的实体确实有字段值发生变化,否则updatedColumns仍会为空。
方案2:QueryBuilder更新时手动记录字段
使用QueryBuilder时,需要在执行更新时主动记录变更的字段,并通过queryRunner的data属性传递给订阅器:
// 执行更新的代码 const updateFields = ['username', 'email']; const queryRunner = connection.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { await queryRunner.manager .createQueryBuilder() .update(User) .set({ username: 'newUser', email: 'new@example.com' }) .where('id = :id', { id: 1 }) .execute(); // 将更新字段存入queryRunner的data中 queryRunner.data.updatedFields = updateFields; await queryRunner.commitTransaction(); } catch (err) { await queryRunner.rollbackTransaction(); } finally { await queryRunner.release(); }
然后在订阅器的afterUpdate事件中读取:
// 订阅器中 const updatedColumnNames = event.queryRunner.data.updatedFields as string[]; console.log('更新的列:', updatedColumnNames);
方案3:对比entity与databaseEntity找出差异
无论使用哪种更新方式,都可以通过对比更新后的实体(event.entity)和数据库中原始实体(event.databaseEntity)的字段值,找出变更的列:
// 在订阅器的afterUpdate方法中 const updatedColumnNames: string[] = []; if (!event.entity || !event.databaseEntity) { return; } event.metadata.columns.forEach(column => { const propName = column.propertyName; const newValue = event.entity[propName]; const oldValue = event.databaseEntity[propName]; // 针对不同类型做比较,比如日期类型转字符串 const isEqual = (() => { if (newValue instanceof Date && oldValue instanceof Date) { return newValue.toISOString() === oldValue.toISOString(); } // 嵌套对象或数组需要深比较,可引入lodash的isEqual等工具 return newValue === oldValue; })(); if (!isEqual) { updatedColumnNames.push(propName); } }); console.log('更新的列:', updatedColumnNames);
注意:这种方法需要处理特殊类型(如日期、嵌套对象)的比较逻辑,避免误判。
内容的提问来源于stack exchange,提问作者Abhimanyu Patil
相关产品推荐
相关产品推荐

