📄 一句话概括
O/R 映射(ORM)=在「对象」和「记录」之间架一部电梯:语言里操作对象,ORM 自动译成 SQL——代码里看不到 SELECT,数据库里全是 SELECT。
📝 本节和前面几节的关系
8-3 的驱动还要手写 SQL,本节更进一步:连 SQL 都藏起来。它回收 C++ 课第十章的类与对象(8-1 表列 ↔ 对象属性)——book.title = '新名' 背后就是一条 UPDATE。ORM 是「数据库进入应用」的最深一层。
一、两个世界的「错位」
| 数据库世界 | 编程语言世界 |
|---|---|
| 表(table) | 类(class) |
| 记录(row) | 对象(object) |
| 列(column) | 属性(field) |
| 外键 | 对象引用 |
ORM 就是把这个对照自动化:定义一个 Book 类,ORM 自动建表/查表/存表。
# Python + SQLAlchemy 风格(示意)
class Book(Base):
__tablename__ = "books"
id = Column(Integer, primary_key=True)
title = Column(String(100))
# 查:不是 SQL,是对象操作
book = session.get(Book, 1)
print(book.title) # '数据库入门'
# 改:改对象属性,再 commit
book.title = "数据库入门(第2版)"
session.commit() # 背后:UPDATE books SET title=... WHERE id=1
二、ORM 的账单
| 收益 | 代价 |
|---|---|
| 用母语开发,类型安全 | 复杂查询生成低效 SQL(7-6 慢查询新来源) |
| 换数据库少改代码 | SQL 被藏起来 → 性能问题难排查 |
| 自动防注入(参数化) | 学习曲线、魔法行为难预测 |
行规:ORM 管日常增删改查;性能关键路径允许手写 SQL(SQL 功底仍是硬通货)。
三、动手 Demo:同一件事的三种写法
-- ① 命令行:手写 SQL(第三章学的方式)
SELECT * FROM books WHERE id = 1;
# ② 驱动层(8-3):SQL 还在,装在字符串里
cur.execute("SELECT * FROM books WHERE id = ?", (1,))
# ③ ORM 层(本节):SQL 消失,对象登场
book = session.get(Book, 1)
【准备块】三种写法对照着看——越往上越像你的语言,越往下越像数据库;ORM 只是③背后自动替你写了①。
四、30 秒实验
把 ORM 想成「代驾」:你说自己家在哪(操作对象),代驾负责开车(生成 SQL)——平时轻松,但复杂路况(复杂查询)你最好还是会开车,否则出了问题连发生了什么都不知道。
五、常见误区
- 「用了 ORM 就不用学 SQL」:恰恰相反——不懂 SQL 的人用 ORM 出了性能问题根本查不出原因(N+1 查询就是经典病)
- 「ORM 生成的 SQL 一定高效」:它保证正确,不保证高效;复杂报表常要手写 SQL 接管
- 「ORM 能防一切错」:它防注入,防不了误删(
session.delete一样真删)——权限与备份照旧
自测三问
1. O/R 映射的四组对应?(表↔类、记录↔对象、列↔属性、外键↔对象引用) 2. ORM 的最大代价?(复杂查询可能低效、SQL 被藏起来难排查——N+1 是经典病) 3. ORM 自动帮你做了哪件安全事?(参数化查询——天然防 7-10 注入)- ☐ 下一节(8-5 Amazon RDS、Cloud SQL、Heroku Postgres-活用云服务)
相关笔记
- 第三方库、驱动程序-在程序中使用数据库 — ORM 站在驱动的肩膀上
- 慢查询-执行时间较长的SQL语句 — ORM 低效 SQL 的归宿:慢查询日志
- Amazon RDS、Cloud SQL、Heroku Postgres-活用云服务 — 下一节:数据库本身也交给别人管
- 🗄️ 数据库基础 · 索引 — 全课路线图