实体监听器和订阅者
什么是实体监听器
您的任何实体都可以具有具有自定义逻辑的方法,用于监听特定的实体事件。 您必须使用特定的装饰器标记这些方法,具体取决于您要监听的事件。
注意:不要在监听器中进行任何数据库调用,而应使用订阅者。
@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 会在使用存储库/管理器的 recover
方法恢复实体后调用它。
示例:
@Entity()
export class Post {
@AfterRecover()
updateStatus() {
this.status = "recovered"
}
}
什么是订阅者
使用 @EventSubscriber
标记一个类为事件订阅者,该订阅者可以监听特定的实体事件或任何实体事件。
事件是通过 QueryBuilder
和存储库/管理器方法触发的。
示例:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
/**
* 指示该订阅者仅监听 Post 事件。
*/
listenTo() {
return Post
}
/**
* 在插入 post 之前调用。
*/
beforeInsert(event: InsertEvent<Post>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
}
您可以实现 EntitySubscriberInterface
中的任何方法。
要监听任何实体,只需省略 listenTo
方法并使用 any
:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* 在实体加载后调用。
*/
afterLoad(entity: any) {
console.log(`AFTER ENTITY LOADED: `, entity)
}
/**
* 在插入 post 之前调用。
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
/**
* 在实体插入后调用。
*/
afterInsert(event: InsertEvent<any>) {
console.log(`AFTER ENTITY INSERTED: `, event.entity)
}
/**
* 在实体更新之前调用。
*/
beforeUpdate(event: UpdateEvent<any>) {
console.log(`BEFORE ENTITY UPDATED: `, event.entity)
}
/**
* 在实体更新后调用。
*/
afterUpdate(event: UpdateEvent<any>) {
console.log(`AFTER ENTITY UPDATED: `, event.entity)
}
/**
* 在实体删除之前调用。
*/
beforeRemove(event: RemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}
/**
* 在实体删除后调用。
*/
afterRemove(event: RemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}
/**
* 在软删除实体之前调用。
*/
beforeSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}
/**
* 在软删除实体后调用。
*/
afterSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}
/**
* 在恢复实体之前调用。
*/
beforeRecover(event: RecoverEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}
/**
* 在恢复实体后调用。
*/
afterRecover(event: RecoverEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}
/**
* 在事务开始之前调用。
*/
beforeTransactionStart(event: TransactionStartEvent) {
console.log(`BEFORE TRANSACTION STARTED: `, event)
}
/**
* 在事务开始后调用。
*/
afterTransactionStart(event: TransactionStartEvent) {
console.log(`AFTER TRANSACTION STARTED: `, event)
}
/**
* 在事务提交之前调用。
*/
beforeTransactionCommit(event: TransactionCommitEvent) {
console.log(`BEFORE TRANSACTION COMMITTED: `, event)
}
/**
* 在事务提交后调用。
*/
afterTransactionCommit(event: TransactionCommitEvent) {
console.log(`AFTER TRANSACTION COMMITTED: `, event)
}
/**
* 在事务回滚之前调用。
*/
beforeTransactionRollback(event: TransactionRollbackEvent) {
console.log(`BEFORE TRANSACTION ROLLBACK: `, event)
}
/**
* 在事务回滚后调用。
*/
afterTransactionRollback(event: TransactionRollbackEvent) {
console.log(`AFTER TRANSACTION ROLLBACK: `, event)
}
}
请确保在 DataSourceOptions 中设置了 subscribers
属性,以便 TypeORM 加载您的订阅者。
事件对象
除了 listenTo
外,EntitySubscriberInterface
的所有方法都会传递一个事件对象,该事件对象具有以下基本属性:
dataSource: DataSource
- 在事件中使用的 DataSource。queryRunner: QueryRunner
- 在事件事务中使用的 QueryRunner。manager: EntityManager
- 在事件事务中使用的 EntityManager。
有关其他属性,请参阅每个 事件接口。
注意:订阅事件监听器中的所有数据库操作应使用事件对象的 queryRunner
或 manager
实例执行。