我对LifcycleHooks和eventsubscriber的概念相当陌生。我试图填充一个历史表,记录在任何其他表上所做的更改。我一直在尝试使用EventSubscriber:这个想法是,在我的eventSubscriber的onFlush事件触发器上,我从更改集中提取所有更改的值和字段,并创建历史表的对象,并试图持久化它,但我看到以下错误:
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason: ValidationError: You cannot call em.flush() from inside lifecycle hook handlers
我的订阅者是这样的:
import { HistoryLog } from 'src/entities/history-log.entity;
export class EntityChangeSubscriber implements EventSubscriber<AnyEntity> {
async afterCreate(args: EventArgs<AnyEntity>): Promise<void> {
console.log('===========1111 AfterCreateHook');
console.log(args.entity);
}
async afterUpdate(args: EventArgs<AnyEntity>): Promise<void> {
console.log('===========2222 AfterUpdateHook');
console.log(args.entity);
}
async onFlush(args: FlushEventArgs): Promise<void> {
console.log('===========3333 onFlushHook');
console.log(args);
const changeSets = args.uow.getChangeSets();
const entities = changeSets.map((cs) => cs.entity);
console.log('Affected entities', entities);
}
async afterFlush(args: FlushEventArgs): Promise<void> {
console.log('===========4444 AfterFlushHook');
const changeSets = args.uow.getChangeSets();
console.log('change sets', changeSets);
changeSets?.map(async (cs) => {
if (cs.persisted) {
console.log('print changeset');
let nextValues = cs.payload ? cs.payload : {};
let tableName = cs.name;
let operation = cs.type;
let rowId = cs.getPrimaryKey()?.toString();
let modifiedFields = Object.keys(cs.payload);
let previousValues = cs.originalEntity ? cs.originalEntity : {};
for (let key in previousValues) {
if (
!previousValues.hasOwnProperty(key) ||
!modifiedFields.includes(key)
) {
delete previousValues[key];
}
}
const historyLog=new HistoryLog({
operation,
tableName,
rowId,
previousValues,
nextValues
});
console.log(historyLog);
let historyLog1= await args.em.persistAndFlush(historyLog);
console.log('historyLog1>>> ',historyLog1);
return historyLog1;
}
});
}
}
我的mikro-orm-postgres.config.ts
注册了订阅者,我可以看到正在加载更改集subscribers: [new EntityChangeSubscriber()]
我如何实现这个?是否有一种方法,我可以将EventSubscriber的结果返回到服务类并在那里进行持久化操作?
不应该从任何钩子或事件处理程序内部刷新。使用刷新事件是正确的,但是您应该使用onFlush
而不是afterFlush
,并将新添加的实体附加到当前的工作单元中。这正是文档中的示例所显示的。
https://mikro-orm.io/docs/lifecycle-hooks/using-onflush-event
如果你想并行地发出查询(而不是在同一个事务中),你可以fork EM来绕过验证错误,或者使用em.nativeInsert()
而不是UoW来创建新记录。