今日內容參考TypeORM官網Embedded Entity及Entity Listener/Subscriber
對於每個Entity都會用的欄位/屬性,可以用partial entity的概念,把相關的屬性獨立出來一個class,增加code reuse。
例如,每個Entity都要建立時間跟上次更新時間
則可以新增EntityDate class如下
@Entity()
export class EntityDate {
@Column({
nullable: true,
})
LastUpdatedDate: Date;
@Column({
nullable: true,
})
createDate: Date;
}
在User、Role及Department都加入下面這段
@Column(type => EntityDate) // 指定column為EntityDate Entity
entityDate: EntityDate; // 型別為EntityDate
在下面Listener& Subscriber部分測試
簡單來說就是Entity有讀取、新增、修改、刪除的動作之前或之後可以做一些事情
主要有以下
大致來看,Listener用在用Repository操作比較多,無法QueryBuilder無法觸發Entity Listener。
以Role Entity為例,假設新增或修改Role時,EntityDate屬性要更新。
@Entity()
export class Role {
...
@ManyToMany(type => User, user => user.roles)
users: User[];
@Column(type => EntityDate)
entityDate: EntityDate ;
@BeforeInsert()
updateDatesWhenInsert(){
// 新增entity前指定現在時間給下列欄位
this.entityDate.createDate = new Date();
this.entityDate.LastUpdatedDate = new Date();
}
@BeforeUpdate()
updateDateWhenUpdate(){
// 更新entity前更新LastUpdatedDate
this.entityDate.LastUpdatedDate = new Date();
}
}
使用Postman測試
對應的SQL指令
對應的SQL指令
Event Listener沒辦法用在User Entity上,因為User Service已經用Query Builder改寫。
如果希望User新增前填入目前時間,新增後加入user權限,根據typeorm官網,可以用Event Subscriber
新增UserSubscriber.ts,注意目錄要放在TypeORModule.forRoot()指定的位置
imports: [
TypeOrmModule.forRoot(
{
type: "postgres",
host: "localhost",
...
subscribers: [ //要放在這裡
"src/shared/subscriber/**/*.ts"
],
},
),
],
可以用typorm cli
typeorm subscriber:create -n UserSubscriber
@EventSubscriber()
export class UserSubscriber implements EntitySubscriberInterface<User> {
listenTo(){
return User;
}
async beforeInsert(event: InsertEvent<User>){
Logger.log(`-----Before Insert------`);
Logger.log(event.entity); // 顯示insert之前entity的資訊
event.entity.entityDate.createDate = new Date();
event.entity.entityDate.LastUpdatedDate = new Date();
}
async afterInsert(event: InsertEvent<User>){
Logger.log(`-----After Insert------`);
// 希望在insert user後自動加入user權限
// 使用Subscriber的好處是可以從event取得entity manager物件
// 進而可以使用querybuilder做任何SQL操作
const role = await event.manager.createQueryBuilder(Role, 'r')
.where('r.roleName = :name', {name: 'user'})
.getOne();
// 要加入user使用relationquerybuilder
event.manager.createQueryBuilder(User, 'u')
.relation('roles')
.of(event.entity)
.add(role);
}
}
不指定roleIds,把userService稍微改寫以後用Postman測試
console畫面可以看到對應的SQL指令