TypeORM:更新项目并返回

san*_*oco 7 rest orm api-design typeorm

据我所知,最佳做法是在更新项目后返回它。TypeORM的updateByIdreturns void,但不是更新的项目。

我的问题:是否可以在一行中更新并返回修改后的项目?

到目前为止我尝试过的是:

await this.taskRepository.updateById(id, { state, dueDate });
return this.taskRepository.findOne({ id });
Run Code Online (Sandbox Code Playgroud)

我在寻找什么:

return this.taskRepository.updateById(id, { state, dueDate }); // returns updated task
Run Code Online (Sandbox Code Playgroud)

san*_*oco 47

我刚刚发现我可以用这个.save方法做到这一点:

return this.taskRepository.save({
    id: task.id,
    state,
    dueDate
});
Run Code Online (Sandbox Code Playgroud)

根据文档(部分save),也支持部分更新:

还支持部分更新,因为所有未定义的属性都被跳过。

  • 请注意,当新实体不存在时,“.save”也会创建一个新实体。这可能并不总是理想的。因此,“.update”将是一个更明智的选择,然后仍然执行“.findOne(id: task.id)”来返回整个对象。 (5认同)
  • 我说的是“..task”变量传播。这只是突然出现的,并不在最初的问题中;在那里你使用“id”。 (4认同)
  • @sandrooco 我纠正了。我做了进一步的测试,它确实返回了完整的实体。我深表歉意,并对答案投了赞成票。此外,我还提出了一些全面的改进措施。因为真正的愿望是更新和返回,而 #save 确实存在创建新实体的陷阱,无论是否有意。 (2认同)

小智 19

为了扩展 Sandrooco 的答案,这就是我所做的:

const property = await this.propertyRepository.findOne({
  where: { id }
});

return this.propertyRepository.save({
  ...property, // existing fields
  ...updatePropertyDto // updated fields
});
Run Code Online (Sandbox Code Playgroud)

  • 这仍然对 Db 进行 2 次调用。有没有办法让它只打一个电话。例如,在 Postgres 中,您可以运行 ``` UPDATE .. SET .. RETURNING * ``` 它将更新数据并返回更新的行 (3认同)

Joe*_*oel 12

虽然我想await Table.update({}, {})退货,Table但它没有。我发现使用 更容易,QueryBuilder因为它总体上给了我更多的控制,但是如果你不喜欢QueryBuilder 或不需要它,你可以做这样的事情:

const post = await Post.update({id}, {...input}).then(response => response.raw[0]);
return post; // returns post of type Post
Run Code Online (Sandbox Code Playgroud)

但是,如果您确实想使用,QueryBuilder我建议采用如下方法。上面的其他人已经提到了Repositoryand Table.save()which的用法并没有真正在type任何地方返回原始内容,所以这种方法对我来说是不合适的。

的一个例子QueryBuilderTable.update({}, {})

@Mutation(() => PostResponse, { nullable: true })
@UseMiddleware(isAuthorized)
async updatePost(
  @Arg("id", () => Int) id: number,
  @Arg("input") input: PostInput,
  @Ctx() { req }: Context
): Promise<PostResponse | null> {

  const { userId } = req.session;
  const errors = validatePost(userId, ...input, await Post.findOne(id));

  if (errors) {
    return { errors };
  }
  // THIS
  const post = await Post.update({id}, {...input}).then(response => response.raw[0]);
  // OR THIS (depending on what approach you want to use)
  const post = await getConnection()
    .createQueryBuilder()
    .update(Post)
    .set({ ...input })
    .where('id = :id and "creatorId" = :creatorId', {
      id,
      creatorId: userId,
    })
    .returning("*")
    .execute()
    .then((response) => {
      return response.raw[0];
    });

  return { post };
}
Run Code Online (Sandbox Code Playgroud)

关键是返回response.raw[0]以获取类型。


注意:我在这里使用 TypeORM 和 Type-GraphQL。

.returning("*") 不适用于 MySQL,请参阅下面的评论。