TypeORM / NestJS - @BeforeUpdate 挂钩不起作用

Dac*_*xj0 4 javascript typeorm nestjs nestjs-config node.js-typeorm

我在使用 TypeOrm 挂钩“BeforeUpdate”时遇到问题

我试图通过传递一个简单的字符串并调用 save 方法来触发 beforeUpdate 挂钩,然后对密码进行哈希处理来更新用户实体密码,但在调用 save 方法时此挂钩不起作用。

这就是我所拥有的

用户服务.ts

async update(id: number, updateUserDto: UpdateUserDto) {
  const roles =
    updateUserDto.roles &&
    (await Promise.all(
      updateUserDto.roles.map((name) => this.preloadRoleByName(name))
    ));
  const user = await this.userRepository.findOneOrFail(id);
  if (!user) {
    throw new NotFoundException(`User with ID #${id} not found`);
  }
  const toSaveUser = {
    ...user,
    ...updateUserDto,
    roles,
  };
  return await this.userRepository.save(toSaveUser);
}
Run Code Online (Sandbox Code Playgroud)

用户实体.ts

.
.
.
@Column()
@Exclude()
password: string;

@BeforeInsert()
@BeforeUpdate()
private async hashPassword() {
  const rounds = 10;
  const salt = await bcrypt.genSalt(rounds);
  this.password = await bcrypt.hash(this.password, salt);
}
Run Code Online (Sandbox Code Playgroud)

用户控制器.ts

@Patch(":id")
@UseInterceptors(ClassSerializerInterceptor)
async update(@Param("id") id: string, @Body() updateUserDto: UpdateUserDto) {
 return await this.usersService.update(+id, updateUserDto);
}
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

BeforeInsert钩子有效,或者如果我调用userRepository.preload()方法来更新它有效,但它不会取代角色的关系,这就是我采用这种方法的原因。

有任何想法吗?

Jon*_*bek 13

使用触发器时需要注意的是,它们可能需要实体的实例才能运行。

Problem:

const user = await this.userRepository.findOneOrFail(id); // entity instance
const toSaveUser = { ...user, ...updateUserDto, roles }; // plain object
return await this.userRepository.save(toSaveUser); // not running trigger
Run Code Online (Sandbox Code Playgroud)

Solution:

const user = await this.userRepository.findOneOrFail(id); // entity instance
// still entity instance
const toSaveUser = this.userRepository.create({
  ...user,
  ...updateUserDto,
  roles,
});
return await this.userRepository.save(toSaveUser); // running trigger

Run Code Online (Sandbox Code Playgroud)

你应该很好。

由于您repository.save()在代码中使用任意对象,因此触发器不会运行。如果我们改为使用repository.create()创建实例,触发器现在将运行。

您的解决方案之所以有效,repository.preload()是因为它返回一个实例。存储库 API 示例