指南

什么是 ORM?应用如何与数据库对话,一文讲清

ORM(对象关系映射器)是一种代码库,位于应用和关系型数据库之间。开发者不必用 SQL 编写数据库查询,而是用编程语言中的普通对象来处理数据,例如 db.booking.create(...) 或 Booking.find(...)。ORM 会把这些操作翻译成 SQL、执行,再把结果转换回对象。常见的例子包括用于 TypeScript 的 Prisma 和 Drizzle、用于 Python 的 SQLAlchemy,以及用于 C# 的 Entity Framework Core。

用 AI 构建应用时,为什么 ORM 很重要

当 AI 应用构建工具为你的应用添加数据库时,它通常也会添加一个 ORM 来与之通信。你不必自己编写 ORM 代码,但了解它的存在仍然很有帮助:

  • 你的数据模型存在于代码中。 ORM 的 schema 文件通常是描述应用数据最清晰的地方:有哪些表、每张表有哪些字段,以及它们如何关联。阅读它是快速检查 AI 是否理解了你的应用的好办法。
  • 数据库的变更通过迁移完成。 当你提出“给客户添加一个电话号码”时,AI 会更新模型并创建一个迁移。了解这一点,有助于你明白为什么某项变更在上线前可能需要先被应用。
  • 默认安全。 ORM 以一种能防范 SQL 注入的方式构建查询。SQL 注入是手工拼接查询的应用中最常见的安全漏洞之一。
  • 性能陷阱。 ORM 很容易让你不经意间执行数百次小查询,而其实一次就够。这是 AI 构建的应用页面变慢的常见原因。

一个日常类比

想象一位英国旅行者和一位日本店主,两人语言不通,靠一位翻译交流。

旅行者(你的应用)说:“我想要你们最便宜的三种茶。”翻译(ORM)把这句话准确地译成日语(SQL),交给店主(数据库),再把答复译回英语。

旅行者无需学会日语,对大多数对话来说这没问题。但在复杂的谈判中,直接开口交流会更有帮助,这也是大多数 ORM 允许开发者在需要时编写原始 SQL 的原因。

ORM 如何工作

像 Postgres 这样的数据库把数据存放在由行和列组成的表中,并使用 SQL 进行查询。编程语言则使用对象来工作:例如一个带有 date、customer 和 status 的预订。ORM 负责在两者之间建立映射:

数据库端ORM / 代码端
表 bookings模型 Booking
行一个预订对象
列 starts_at字段 startsAt
外键 customer_id关系 booking.customer
SELECT、INSERT、UPDATE、DELETEfind、create、update、delete 方法

这四种操作就是几乎所有应用都依赖的 CRUD 操作。

实例演示:用 Prisma 处理预订

下面是一个为美发沙龙预订应用编写的简化版 Prisma schema,它描述了两张表以及它们之间的关联:

model Customer {
  id       Int       @id @default(autoincrement())
  name     String
  email    String    @unique
  bookings Booking[]
}

model Booking {
  id         Int      @id @default(autoincrement())
  startsAt   DateTime
  service    String
  customer   Customer @relation(fields: [customerId], references: [id])
  customerId Int
}

用通俗的话说:一位客户有姓名、唯一的邮箱,并且可以有多次预订;每次预订有开始时间和服务项目,并且只属于一位客户。

现在应用需要查询“Lena 即将到来的预订,最早的排在前面”:

const bookings = await db.booking.findMany({
  where: {
    customer: { email: "lena@example.com" },
    startsAt: { gte: new Date() },
  },
  orderBy: { startsAt: "asc" },
});

ORM 会把它转换成大致如下的 SQL,执行后返回一个预订对象列表:

SELECT b.* FROM "Booking" b
JOIN "Customer" c ON c.id = b."customerId"
WHERE c.email = $1 AND b."startsAt" >= $2
ORDER BY b."startsAt" ASC;

其中 $1 和 $2 是占位符:邮箱和日期与查询语句分开发送,这正是防止 SQL 注入的原因。

迁移

如果你接着提出“让客户可以添加电话号码”,AI 会在 Customer 模型中加入 phone String?(? 表示可选),并生成一个迁移,也就是类似 ALTER TABLE "Customer" ADD COLUMN "phone" TEXT; 的小型 SQL 脚本。迁移按顺序保存,因此每一份数据库副本都可以被同步到相同的结构,并且变更历史会被保留。

各语言常用的 ORM

语言常用 ORM
TypeScript / JavaScriptPrisma、Drizzle、TypeORM、Sequelize
PythonSQLAlchemy、Django ORM、SQLModel
C#Entity Framework Core
JavaHibernate(通常通过 Spring Data JPA 使用)
RubyActive Record

ORM 对 SQL 的隐藏程度各不相同。Prisma 使用自己的 schema 语言和查询风格;Drizzle 则刻意贴近 SQL 的结构,同时保持全部类型化。另外一类较轻量的工具叫做查询构建器,例如 TypeScript 中的 Knex 或 Kysely,它们帮助你在代码中构建 SQL,但不会把行映射为完整的对象。

关键术语

术语含义
模型(Model)对某张表及其字段的代码定义。
Schema对所有表、字段和关系的完整描述。
关系(Relation)模型之间的链接,例如某次预订属于某位客户。
迁移(Migration)用于修改数据库结构的带版本号的脚本。
查询构建器(Query builder)一种较轻量的工具,用于在代码中构建 SQL,而不做完整的对象映射。
N+1 问题先执行一次查询获取列表,再为每一项各执行一次查询——数据量大时会很慢。
原始 SQL(Raw SQL)手写的 SQL,在 ORM 成为阻碍时使用。

常见误解

  • “ORM 就是数据库。” 并不是。它是一个翻译器。你仍然需要像 Postgres 这样的数据库。
  • “用了 ORM 就不需要理解你的数据。” 设计糟糕的表无论通过 ORM 还是其他方式使用,都同样令人头疼。好的数据模型比工具本身更重要。
  • “ORM 总是很慢。” 日常查询没有问题。慢通常来自 N+1 查询或缺失索引等模式,而这些都是可以修复的。
  • “使用 ORM 就永远不会有 SQL 注入风险。” 标准的 ORM 方法是安全的,但如果把用户输入直接拼接进原始 SQL,仍然很危险。
  • “修改 schema 文件就会改变线上数据库。” 只有在创建迁移并将其应用到该数据库之后才会如此。

向你的 AI 构建工具提出的要求

  • “展示数据库 schema,并用通俗的语言解释每张表和每个关系。”
  • “这个项目使用哪个 ORM?迁移文件在哪里?”
  • “在修改任何表之前,先告诉我现有数据是否会受影响;未经询问,绝不删除仍有数据的字段。”
  • “检查最慢的页面是否存在 N+1 查询,并在列表被筛选或排序的字段上添加索引。”
  • “确保每个使用用户输入的查询都通过 ORM 或使用参数——不要拼接 SQL 字符串。”

Mythex 中的 ORM

当你的应用需要保存数据时,Mythex 会为项目添加一个专用的 Postgres 数据库。你可以在聊天中提出需求,也可以使用 /database 命令。Mythex 会把连接信息注入工作区和已发布的应用中(数据库文档)。之后,由智能体编写读取和保存数据的代码。如果你有偏好,比如“使用 Prisma”“使用 SQLAlchemy”或“使用原生 SQL,不要 ORM”,请直接在聊天中说明。你随时可以让它为你讲解 schema,也可以在代码编辑器中查看这些文件。想了解更全面的内容,请参阅什么是数据库和 SQL 与 NoSQL 对比。

常见问题

用简单的话说,什么是 ORM?

ORM(对象关系映射器)是一种代码库,位于你的应用和关系型数据库之间。开发者可以用编程语言中的普通对象来读写数据,ORM 则在幕后替他们编写 SQL 查询。

常见的 ORM 有哪些例子?

常见的 ORM 包括适用于 TypeScript 和 JavaScript 的 Prisma 与 Drizzle,适用于 Python 的 SQLAlchemy 和 Django ORM,适用于 C# 的 Entity Framework Core,适用于 Java 的 Hibernate,以及 Ruby on Rails 中的 Active Record。

ORM 比直接写 SQL 更好吗?

这取决于具体工作。ORM 让日常的读写更快编写、更安全、更易修改;而手写 SQL 则能为复杂报表或对性能要求高的查询提供完全的控制。大多数 ORM 在需要时都允许你直接使用原始 SQL。

什么是迁移(migration)?

迁移是一个小型的、带版本号的脚本,用于修改数据库结构,例如新增一张表或一个字段。ORM 可以根据你的数据模型生成迁移,让每一份数据库副本(无论是在笔记本电脑、测试环境还是生产环境中)都保持相同的结构。

Mythex · Pricing · 用 AI 构建任何东西 · 网站和应用模板 · Mythex 对比 · AI 应用构建术语表 · 免费的 AI 应用构建工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 繁體中文(香港) 繁體中文(台灣)