实体监听器与订阅者
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
什么是实体监听器?
您可以在任何实体中创建包含自定义逻辑的方法,用于监听特定实体事件。这些方法需要使用特殊装饰器进行标记,具体取决于您要监听的事件类型。
注意: 请勿在监听器内执行任何数据库操作,应改用订阅者。
@AfterLoad
您可以在实体中定义任意名称的方法并用 @AfterLoad 标记,
TypeORM 将在每次通过 QueryBuilder 或仓库/管理器查询方法加载实体时调用它。
示例:
@Entity()
export class Post {
@AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}
@BeforeInsert
您可以在实体中定义任意名称的方法并用 @BeforeInsert 标记,
TypeORM 将在通过仓库/管理器 save 方法插入实体前 调用它。
示例:
@Entity()
export class Post {
@BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}
@AfterInsert
您可以在实体中定义任意名称的方法并用 @AfterInsert 标记,
TypeORM 将在通过仓库/管理器 save 方法插入实体后调用它。
示例:
@Entity()
export class Post {
@AfterInsert()
resetCounters() {
this.counters = 0
}
}
@BeforeUpdate
您可以在实体中定义任意名称的方法并使用@BeforeUpdate标记,TypeORM 将在通过仓库/管理器的save方法更新现有实体前自动调用该方法。请注意:仅当模型数据发生变更时才会触发。若执行save时未修改模型数据,则@BeforeUpdate和@AfterUpdate不会执行。
示例:
@Entity()
export class Post {
@BeforeUpdate()
updateDates() {
this.updatedDate = new Date()
}
}
@AfterUpdate
您可以在实体中定义任意名称的方法并用 @AfterUpdate 标记,
TypeORM 将在通过仓库/管理器 save 方法更新现有实体后调用它。
示例:
@Entity()
export class Post {
@AfterUpdate()
updateCounters() {
this.counter = 0
}
}
@BeforeRemove
你可以在实体中定义一个任意名称的方法,并用 @BeforeRemove 标记。TypeORM 会在实体被仓库/管理器的 remove 方法移除之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeRemove()
updateStatus() {
this.status = "removed"
}
}
@AfterRemove
您可以在实体中定义任意名称的方法并用 @AfterRemove 标记,
TypeORM 将在通过仓库/管理器 remove 方法移除实体后调用它。
示例:
@Entity()
export class Post {
@AfterRemove()
updateStatus() {
this.status = "removed"
}
}
@BeforeSoftRemove
你可以在实体中定义一个任意名称的方法,并用 @BeforeSoftRemove 标记。TypeORM 会在实体被仓库/管理器的 softRemove 方法软删除之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
@AfterSoftRemove
您可以在实体中定义任意名称的方法并用 @AfterSoftRemove 标记,
TypeORM 将在通过仓库/管理器 softRemove 方法软删除实体后调用它。
示例:
@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
@BeforeRecover
你可以在实体中定义一个任意名称的方法,并用 @BeforeRecover 标记。TypeORM 会在实体被仓库/管理器的 recover 方法恢复之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeRecover()
updateStatus() {
this.status = "recovered"
}
}
@AfterRecover
您可以在实体中定义任意名称的方法,并使用 @AfterRecover 标记,
TypeORM 会在通过 repository/manager 的 recover 方法恢复实体后调用该方法。
示例:
@Entity()
export class Post {
@AfterRecover()
updateStatus() {
this.status = "recovered"
}
}
什么是订阅者?
将类标记为事件订阅者,可监听特定实体事件或所有实体事件。事件通过QueryBuilder及仓库/管理器的方法触发。
示例:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
/**
* Indicates that this subscriber only listen to Post events.
*/
listenTo() {
return Post
}
/**
* Called before post insertion.
*/
beforeInsert(event: InsertEvent<Post>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
}
您可以实现EntitySubscriberInterface中的任意方法。要监听所有实体事件,只需省略listenTo方法并使用any:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* Called after entity is loaded.
*/
afterLoad(entity: any) {
console.log(`AFTER ENTITY LOADED: `, entity)
}
/**
* Called before query execution.
*/
beforeQuery(event: BeforeQueryEvent<any>) {
console.log(`BEFORE QUERY: `, event.query)
}
/**
* Called after query execution.
*/
afterQuery(event: AfterQueryEvent<any>) {
console.log(`AFTER QUERY: `, event.query)
}
/**
* Called before entity insertion.
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE ENTITY INSERTED: `, event.entity)
}
/**
* Called after entity insertion.
*/
afterInsert(event: InsertEvent<any>) {
console.log(`AFTER ENTITY INSERTED: `, event.entity)
}
/**
* Called before entity update.
*/
beforeUpdate(event: UpdateEvent<any>) {
console.log(`BEFORE ENTITY UPDATED: `, event.entity)
}
/**
* Called after entity update.
*/
afterUpdate(event: UpdateEvent<any>) {
console.log(`AFTER ENTITY UPDATED: `, event.entity)
}
/**
* Called before entity removal.
*/
beforeRemove(event: RemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}
/**
* Called after entity removal.
*/
afterRemove(event: RemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}
/**
* Called before entity removal.
*/
beforeSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}
/**
* Called after entity removal.
*/
afterSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}
/**
* Called before entity recovery.
*/
beforeRecover(event: RecoverEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}
/**
* Called after entity recovery.
*/
afterRecover(event: RecoverEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}
/**
* Called before transaction start.
*/
beforeTransactionStart(event: TransactionStartEvent) {
console.log(`BEFORE TRANSACTION STARTED: `, event)
}
/**
* Called after transaction start.
*/
afterTransactionStart(event: TransactionStartEvent) {
console.log(`AFTER TRANSACTION STARTED: `, event)
}
/**
* Called before transaction commit.
*/
beforeTransactionCommit(event: TransactionCommitEvent) {
console.log(`BEFORE TRANSACTION COMMITTED: `, event)
}
/**
* Called after transaction commit.
*/
afterTransactionCommit(event: TransactionCommitEvent) {
console.log(`AFTER TRANSACTION COMMITTED: `, event)
}
/**
* Called before transaction rollback.
*/
beforeTransactionRollback(event: TransactionRollbackEvent) {
console.log(`BEFORE TRANSACTION ROLLBACK: `, event)
}
/**
* Called after transaction rollback.
*/
afterTransactionRollback(event: TransactionRollbackEvent) {
console.log(`AFTER TRANSACTION ROLLBACK: `, event)
}
}
请确保在您的 DataSourceOptions 中设置了 subscribers 属性,这样 TypeORM 才能加载您的订阅者。
Event Object
除 listenTo 方法外,所有 EntitySubscriberInterface 接口的方法都会接收一个包含以下基础属性的事件对象:
-
dataSource: DataSource- 事件中使用的 DataSource。 -
queryRunner: QueryRunner- 事件事务中使用的 QueryRunner。 -
manager: EntityManager- 事件事务中使用的 EntityManager。
请查看各事件接口获取额外属性信息。
请注意:当使用 Repository.update() 方法时,event.entity 不一定包含主键值。只有实体部分更新中提供的值才可用。若要在订阅者中获取主键,您可以在部分实体对象字面 量中显式传递主键值,或改用会执行重新获取操作的 Repository.save() 方法。
await postRepository.update(post.id, { description: "Bacon ipsum dolor amet cow" })
// post.subscriber.ts
afterUpdate(event: UpdateEvent<Post>) {
console.log(event.entity) // outputs { description: 'Bacon ipsum dolor amet cow' }
}
注意: 所有在订阅事件监听器中的数据库操作都应通过事件对象的 queryRunner 或 manager 实例执行。