使用 EventSubscriber 在 mikroorm 中注册 Database History
Use EventSubscriber to register Database History in mikroorm
我对 LifcycleHooks 和 EventSubscribers 的概念还很陌生。我正在尝试填充一个历史 table 来记录对任何其他 table 所做的更改。我一直在尝试为此使用 EventSubscriber:
我的想法是,在我的 eventSubscriber 的 onFlush 事件触发器上,我从变更集中提取所有已更改的值和字段,并创建一个历史对象 table 并尝试保留它,但我看到以下错误:
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()]
我该如何实施?有没有一种方法可以 return 将 EventSubscriber 的结果发送到服务 class 并在那里执行持久操作?
您不应从任何挂钩或事件处理程序内部刷新。使用刷新事件是正确的,但您应该使用 onFlush
而不是 afterFlush
并将新添加的实体附加到当前工作单元。这正是文档中示例显示的内容。
https://mikro-orm.io/docs/lifecycle-hooks/#using-onflush-event
如果您想并行发出查询(不在同一事务中),您可以分叉 EM 来绕过验证错误,或者使用 em.nativeInsert()
而不是 UoW 来创建新记录.
我对 LifcycleHooks 和 EventSubscribers 的概念还很陌生。我正在尝试填充一个历史 table 来记录对任何其他 table 所做的更改。我一直在尝试为此使用 EventSubscriber: 我的想法是,在我的 eventSubscriber 的 onFlush 事件触发器上,我从变更集中提取所有已更改的值和字段,并创建一个历史对象 table 并尝试保留它,但我看到以下错误:
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()]
我该如何实施?有没有一种方法可以 return 将 EventSubscriber 的结果发送到服务 class 并在那里执行持久操作?
您不应从任何挂钩或事件处理程序内部刷新。使用刷新事件是正确的,但您应该使用 onFlush
而不是 afterFlush
并将新添加的实体附加到当前工作单元。这正是文档中示例显示的内容。
https://mikro-orm.io/docs/lifecycle-hooks/#using-onflush-event
如果您想并行发出查询(不在同一事务中),您可以分叉 EM 来绕过验证错误,或者使用 em.nativeInsert()
而不是 UoW 来创建新记录.