TypeORM 技巧(第一部分:不要使用 save())

2025-06-10

TypeORM 技巧(第一部分:不要使用 save())

系列简介

截至 2022 年 1 月 21 日(来源),TypeORM 是第三流行的Javascript ORM 库,如果我们谈论的是 Typescript,它无疑是最受欢迎的。

过去两年来,我一直在深入使用这个库,每天用它处理数百万次数据库查询。在本系列文章中,我将列出我在使用这个项目过程中学到的一些技巧和陷阱,这些技巧和陷阱帮助我在生产环境中捕获错误并优化 API 调用。我会尽量保持每篇文章简短、信息丰富且通俗易懂,以便您能够在代码中快速运用这些优化方法。

在每篇文章中,我们将讨论:

  1. 问题是什么?
  2. 为什么是错的?
  3. 你怎么能修复它?

那么让我们开始吧!

save() 与 insert()、update()

存储库具有该.save()方法,该方法具有双重功能:

  1. 如果实体尚不存在,则插入该实体。
  2. 如果实体存在,它会尝试更新现有实体。

让我们观察一下该方法的两个示例用法:

以下是从注册新用户的 API 端点获取的代码片段:

const user = this.userRepository.create({
    name: "Rishit",
    password: "test123",
});
await this.userRepository.save(user);
Enter fullscreen mode Exit fullscreen mode

以下是来自另一个端点的片段,用于更新现有用户的名称:

const user = this.userRepository.findOne({
    name: "Rishit",
});
user.name = "John";
await this.userRepository.save(user);
Enter fullscreen mode Exit fullscreen mode

很方便吧?其实也没那么方便,因为性能会有所下降。 的实现save()会执行两个查询,而不是一个:

  1. 首先,它使用SELECT查询来搜索现有实体。
  2. 如果步骤 1 返回一条记录,则用于UPDATE更新该记录。否则,用于INSERT插入一条新记录。

为什么不好?

  1. 这些查询需要两次往返数据库,这意味着您必须忍受每次往返造成的网络延迟。
  2. 您的代码中存在特定的上下文,您确实知道您正在插入/更新,并且不需要使用save()的双重功能。
  3. TypeORM 生成的查询SELECT包含子查询,这对于具有数百万行的表来说效率极低。

如何修复这个问题?

查看使用查询的上下文,通常可以让你决定是要执行insert()还是update()。例如,你可以将上面两个代码片段重构为:

注册新用户:

const user = this.userRepository.create({
    name: "Rishit",
    password: "test123",
});
await this.userRepository.insert(user);
Enter fullscreen mode Exit fullscreen mode

更新现有用户:

await this.userRepository.update({
    name: "Rishit",
},{
    name: "John",
});
Enter fullscreen mode Exit fullscreen mode

就这样,您将这些查询导致的数据库负载减少了一半:性能提升了2 倍! 的用法可能看起来很明显。尽管如此,由于TypeORM 本身的文档推荐它作为更新实体的主要模式,save()因此它仍然是代码中普遍使用的做法。.save()

话虽如此,这确实为需要根据实体是否存在进行“或save()操作的代码提供了一个有效的用例。然而,我确信大多数用例并不需要这个功能,它们只想插入或更新记录,而不是两者兼而有之。insertupdate

鏂囩珷鏉ユ簮锛�https://dev.to/rishit/optimizing-typeorm-tips-from-experience-part-1-dont-use-save-4ke9
PREV
Docker 释放:掌握命令、基础知识、学习资源和职业前景
NEXT
构建 React 应用程序——我从作为一名 Web 开发人员的经验中学到的东西