# Entity Listeners and Subscribers
# What is an Entity Listener
Any of your entities can have methods with custom logic that listen to specific entity events. You must mark those methods with special decorators depending on what event you want to listen to.
Note: Do not make any database calls within a listener, opt for subscribers instead.
# @AfterLoad
You can define a method with any name in entity and mark it with @AfterLoad
and TypeORM will call it each time the entity
is loaded using QueryBuilder
or repository/manager find methods.
Example:
@Entity()
export class Post {
@AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}
2
3
4
5
6
7
# @BeforeInsert
You can define a method with any name in entity and mark it with @BeforeInsert
and TypeORM will call it before the entity is inserted using repository/manager save
.
Example:
@Entity()
export class Post {
@BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}
2
3
4
5
6
7
# @AfterInsert
You can define a method with any name in entity and mark it with @AfterInsert
and TypeORM will call it after the entity is inserted using repository/manager save
.
Example:
@Entity()
export class Post {
@AfterInsert()
resetCounters() {
this.counters = 0
}
}
2
3
4
5
6
7
# @BeforeUpdate
You can define a method with any name in the entity and mark it with @BeforeUpdate
and TypeORM will call it before an existing entity is updated using repository/manager save
. Keep in mind, however, that this will occur only when information is changed in the model. If you run save
without modifying anything from the model, @BeforeUpdate
and @AfterUpdate
will not run.
Example:
@Entity()
export class Post {
@BeforeUpdate()
updateDates() {
this.updatedDate = new Date()
}
}
2
3
4
5
6
7
# @AfterUpdate
You can define a method with any name in the entity and mark it with @AfterUpdate
and TypeORM will call it after an existing entity is updated using repository/manager save
.
Example:
@Entity()
export class Post {
@AfterUpdate()
updateCounters() {
this.counter = 0
}
}
2
3
4
5
6
7
# @BeforeRemove
You can define a method with any name in the entity and mark it with @BeforeRemove
and TypeORM will call it before a entity is removed using repository/manager remove
.
Example:
@Entity()
export class Post {
@BeforeRemove()
updateStatus() {
this.status = "removed"
}
}
2
3
4
5
6
7
# @AfterRemove
You can define a method with any name in the entity and mark it with @AfterRemove
and TypeORM will call it after the entity is removed using repository/manager remove
.
Example:
@Entity()
export class Post {
@AfterRemove()
updateStatus() {
this.status = "removed"
}
}
2
3
4
5
6
7
# @BeforeSoftRemove
You can define a method with any name in the entity and mark it with @BeforeSoftRemove
and TypeORM will call it before a entity is soft removed using repository/manager softRemove
.
Example:
@Entity()
export class Post {
@BeforeSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
2
3
4
5
6
7
# @AfterSoftRemove
You can define a method with any name in the entity and mark it with @AfterSoftRemove
and TypeORM will call it after the entity is soft removed using repository/manager softRemove
.
Example:
@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
2
3
4
5
6
7
# @BeforeRecover
You can define a method with any name in the entity and mark it with @BeforeRecover
and TypeORM will call it before a entity is recovered using repository/manager recover
.
Example:
@Entity()
export class Post {
@BeforeRecover()
updateStatus() {
this.status = "recovered"
}
}
2
3
4
5
6
7
# @AfterRecover
You can define a method with any name in the entity and mark it with @AfterRecover
and TypeORM will call it after the entity is recovered using repository/manager recover
.
Example:
@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "recovered"
}
}
2
3
4
5
6
7
# What is a Subscriber
Marks a class as an event subscriber which can listen to specific entity events or any entity events.
Events are firing using QueryBuilder
and repository/manager methods.
Example:
@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)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
You can implement any method from EntitySubscriberInterface
.
To listen to any entity you just omit listenTo
method and use any
:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* Called after entity is loaded.
*/
afterLoad(entity: any) {
console.log(`AFTER ENTITY LOADED: `, entity)
}
/**
* Called before post insertion.
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE POST 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 removal.
*/
beforeRecover(event: RecoverEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}
/**
* Called after entity removal.
*/
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)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
Make sure your subscribers
property is set in your DataSourceOptions so TypeORM loads your subscriber.
# Event Object
Excluding listenTo
, all EntitySubscriberInterface
methods are passed an event object that has the following base properties:
dataSource: DataSource
- DataSource used in the event.queryRunner: QueryRunner
- QueryRunner used in the event transaction.manager: EntityManager
- EntityManager used in the event transaction.
See each Event's interface (opens new window) for additional properties.
Note: All database operations in the subscribed event listeners should be performed using the event object's queryRunner
or manager
instance.