iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 21
0
Modern Web

讀官網文件邊走邊學nest.js系列 第 21

Day21-TypeORM(八) RelationQueryBuilder(上)

  • 分享至 

  • xImage
  •  

今天參考TypeORM官網RelationBuilder

RelationQueryBudiler

顧名思義,RelationQuberyBuilder是特殊的QueryBuilder,typeorm提供來簡化Entity Relations的操作,今天以更新為例

one-to-many/many-to-one

先從最簡單的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測試

many-to-many

與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測試

Refactor AppService裡面的更新使用者方法

把前面兩個合起來,就可以完整更新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


上一篇
Day20-TypeORM(七) Query Builder Select(下)
下一篇
Day 22-TypeORM(九) RelationQueryBuilder(下) & Refactor
系列文
讀官網文件邊走邊學nest.js31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言