顧名思義,RelationQuberyBuilder是特殊的QueryBuilder,typeorm提供來簡化Entity Relations的操作,今天以更新為例
先從最簡單的one-to-many/many-to-one,更新使用者所屬部門為例,
在user.service新增
async updateUserDepById(userId, depId){ // 傳入userId及depId
await this.userRepo.createQueryBuilder()
.relation(User, 'dep') // 指定載入relation
.of(userId) // 找對應的entity,可以是id或是queryed entity
.set(depId) // 更新(或是新增)depId
//.then(result => result); 回傳void
return await this.userRepo.findOne(userId, {relations: ['dep', 'roles']}); // 回傳結果
}
在app.controller.ts新增
@Put(':userId/:depId')
updateUserDepById(@Param('userId') userId, @Param('depId') depId){
return this.usersService.updateUserDepById(userId, depId);
}
使用postman測試
與one-to-many差異不大,差別在於many-to-many用的是add或是addAndRemove
async updateUserRolesByIds(userId, data: UserDTO){
//更新roles,必須先取的資料庫現有的資料
const user = await this.userRepo.findOne(userId, {relations: ['roles']});
Logger.log(user);
await this.userRepo.createQueryBuilder()
.relation(User, 'roles') // 指定載入relation
.of(userId) // 找對應的entity,可以是id或是queryed entity
// 第一個參數是要新增的roles,第二個參數是要移除的roles
// 當然可以用lodash對陣列做操作,得到新增的陣列跟移除的陣列
// 但builder API一次只能有add或是remove,所以用addAndRemove是最快的
.addAndRemove(data.roleIds, user.roles.map(role => role.id))
//.then(result => return result); 回傳void
return await this.userRepo.findOne(userId, {relations: ['dep', 'roles']});
}
為了測試方便,先修改原本AppController下的@Put(':userId')
@Put(':userId')
updateUserById(@Param('userId') id, @Body() userDTO: UserDTO){
//return this.usersService.updateUserById(id, userDTO);
return this.usersService.updateUserRolesByIds(id, userDTO);
}
使用postman測試
把前面兩個合起來,就可以完整更新User資料
修改app.service下updateUserById方法
async updateUserById(userId, data: UserDTO){
const user = await this.userRepo.findOne(userId, {relations: ['roles']});
await this.userRepo.createQueryBuilder()
.relation(User, 'roles')
.of(userId)
.addAndRemove(data.roleIds, user.roles.map(role => role.id))
.then(async () => { // 要串
await this.userRepo.createQueryBuilder()
.relation(User, 'dep')
.of(userId)
.set(data.depId);
});
await this.userRepo.createQueryBuilder() // 更新非relation相關資料
.update(User) // 指定update哪一個entity
.set({ // 更新資料物件
username: data.username,
email: data.email,
})
// whereInIds是helper method
// 原本應為
// .where('id = :id', {id: userId})
.whereInIds(userId)
// .printSql() 可以用來除錯
.execute(); // 執行
return await this.userRepo.findOne(userId, {relations: ['dep', 'roles']});
}
app.controller修改回原本
@Put(':userId')
updateUserById(@Param('userId') id, @Body() userDTO: UserDTO){
return this.usersService.updateUserById(id, userDTO);
// return this.usersService.updateUserRolesByIds(id, userDTO);
}
使用postman測試
console輸出的sql碼
其餘user service下的新增、刪除、查詢用querybuilder refactor,明天繼續
Github source code