LESSON 6.3 / DATABASE & STATE

ORM、Schema 与数据库迁移

ORM 把代码对象映射到数据库操作,迁移则记录表结构怎样一步步变化。两者都不能取代对实际 SQL 和数据风险的理解。

预计阅读约 25 到 40 分钟
完成结果为任务模型生成一次可审查迁移,在练习库应用并回查结构与数据。
本课目标
  • 为任务模型生成一次可审查迁移,在练习库应用并回查结构与数据。
  • Prisma / JPA 等 ORM 与 SQL 的关系
  • 观察ORM、Schema 与数据库迁移后,应当为任务模型生成一次可审查迁移,在练习库应用并回查结构与数据,并保留查询结果、影响行数、迁移记录和缓存命中情况作为可重复检查的依据。
开始之前
  • 完成 6.2「SQL 与关系型数据库直觉」
01

FOUNDATION

必须理解

ORM(Object-Relational Mapping,对象关系映射)把代码中的模型与数据库操作连接起来;迁移则记录数据库结构怎样从旧版本演进到新版本。便利不能替代对 SQL 和数据风险的理解。

本课依次讲清Prisma / JPA 等 ORM 与 SQL 的关系、Schema、客户端、查询和关系加载和迁移文件、开发数据库与生产数据库,最后通过“用 Prisma Client 完成创建、查询、更新并核对数据库”检查学习结果。

先建立整体直觉

ORM 像翻译员,把 TypeScript 对象翻成 SQL;迁移像建筑改造图纸,按顺序记录加门、改管线。翻译员和图纸都可能出错,所以施工前要审查。

贯穿本课的实际场景

Prisma schema 定义 User 与 Task,迁移创建表和外键,服务端通过 Prisma Client 查询当前用户任务;新增 dueAt 字段要生成并检查迁移。

概念 1

Prisma / JPA 等 ORM 与 SQL 的关系

先用白话理解

Prisma Schema 写清模型、字段、关系和约束,Prisma Client 再根据它生成带类型的查询方法。最后确实执行工作的仍然是数据库和 SQL。

基础概念

ORM(Object-Relational Mapping,对象关系映射)把程序中的类型或对象操作映射为数据库查询。Prisma、JPA 等减少重复代码,但底层仍由 SQL 与数据库执行。

进一步理解

ORM 模型描述字段、关系和约束,客户端提供类型化查询。它能防止部分拼接错误,却不会自动设计正确业务模型或高效查询。

复杂查询、事务和性能问题仍需理解生成的 SQL、索引与数据库行为。不同 ORM 的加载策略也可能造成大量隐形请求。

放进实际场景

代码通过 `task.findMany({where:{ownerId}})` 查询任务,ORM 生成参数化 SQL;开发者仍要确认只返回当前用户且没有 N+1 查询。

容易混淆的地方

ORM 不是数据库,也不是 SQL 替代物;它是应用与关系型数据库之间的一层映射和工具。

这一小节记住:使用 ORM 提高表达和类型安全,同时保留检查数据库行为的能力。

概念 2

Schema、客户端、查询和关系加载

先用白话理解

迁移文件记录数据库结构每一步怎么变化,像 Git 记录代码历史。开发时可以反复试,到了生产环境就得考虑旧数据、锁表时间和失败后怎么处理。

基础概念

Schema 是数据结构与约束的声明,生成客户端把声明转换为可调用 API,关系加载决定查询时是否以及怎样取得关联记录。

进一步理解

一对多关系通常由“多”方保存外键。是否一起加载关联数据应由当前用例决定,默认全部加载会增加查询和传输。

Schema 改变只是代码层意图,真实数据库还需迁移。生成客户端也需与新 Schema 同步,否则类型和数据库会处于不同版本。

放进实际场景

Task 的 ownerId 保存外键,owner 描述 ORM 关系;列表页只选择任务字段,详情页需要时再加载所有者公开信息。

容易混淆的地方

类型中的可选字段与数据库可空约束相关但不完全相同;应用没传值、数据库默认值与实际 NULL 要分别理解。

这一小节记住:Schema 描述数据契约,查询应只加载当前行为需要的字段与关系。

概念 3

迁移文件、开发数据库与生产数据库

先用白话理解

如果旧表里已经有一万行数据,突然加一个必填字段,这一万行都没有值。更稳的做法通常是先允许为空、完成回填,再把约束收紧。

基础概念

迁移文件记录数据库结构从一个版本变到下一个版本的具体步骤。开发库用于试验,生产库含真实数据,执行策略必须考虑兼容、锁表、回填和失败恢复。

进一步理解

新增非空字段时,旧行没有值。安全过程常分为增加可空字段、部署兼容代码、回填旧数据、再收紧约束。

迁移应进入版本控制并先在含真实规模副本上演练。直接手改生产表会让源码、迁移历史和实际结构失去一致。

放进实际场景

为任务增加 priority:先允许为空并让新代码兼容,批量回填默认值,验证无 NULL 后再添加非空约束。

容易混淆的地方

代码回滚不自动回滚数据库。某些结构删除和数据转换不可逆,必须单独设计向前修复或恢复方案。

这一小节记住:数据库结构变化要被记录、审查、演练,并与应用版本保持兼容。

Prisma 关系模型
运行前先确认
  • Prisma Schema 中已经存在 User 模型及其 tasks 反向关系。
  • 生成迁移前确认目标数据库与现有数据,不直接对生产执行开发重置。
model Task {
  id        String   @id @default(cuid())
  title     String
  done      Boolean  @default(false)
  ownerId   String
  owner     User     @relation(fields: [ownerId], references: [id])
  createdAt DateTime @default(now())
}
这段代码在做什么

阅读ORM、Schema 与数据库迁移示例时,ownerId 是外键值,owner 描述 Prisma 层关系;数据库迁移会建立相应约束。

  1. id 使用 cuid 生成主键,done 与 createdAt 由数据库/客户端提供默认值。
  2. ownerId 保存真实外键值,owner 声明该字段引用 User.id。
  3. 修改模型后需生成并审查迁移 SQL,再更新客户端类型。
你应该观察到

迁移创建任务表、外键和默认值;无效 ownerId 被约束拒绝,查询时可以按需加载 owner,而不是复制用户数据。

02

AI COLLABORATION

AI 如何参与

在ORM、Schema 与数据库迁移这一课,AI 负责根据真实材料解释Prisma / JPA 等 ORM 与 SQL 的关系并指出遗漏,学习者负责控制范围、执行修改和核对查询结果、影响行数、迁移记录和缓存命中情况。

推荐协作顺序

  1. 1

    把当前 schema、目标变化和已有数据情况发给 AI。

  2. 2

    让它先说明旧数据会遇到什么,再给分阶段迁移方案。

  3. 3

    生成迁移后请它解释 SQL,但最终以测试数据库的真实结果为准。

可直接使用的 Prompt
这是当前模型、数据库结构和生成迁移。请逐项比较差异,指出会创建、修改或丢失什么。不要直接操作生产库,不自动接受删除列。给出应用前备份、练习库验证和回退检查。
应该得到什么

模型有清晰主键、外键和时间字段;迁移方案考虑旧数据,不只给 prisma migrate 命令;ORM、Schema 与数据库迁移的人工验收必须回到真实页面、请求、终端、测试或数据结果,不能用 AI 的文字说明代替。

人工检查清单

  • 确认没有保存明文密码,级联删除符合产品意图,生成的迁移 SQL 会被人工检查。
  • 让 AI 展示迁移实际 SQL、旧数据处理和新旧应用并存时的兼容路径。
  • 在含旧数据的测试副本执行迁移、回退或恢复演练,并核对行数与约束。
03

COMMON TRAPS

常见误区

下面三类问题会让任务看似完成,却经不起刷新、错误输入或真实环境检查。先看现象,再找原因和修正方法。

误区 1

盲信自动生成迁移

你会看到
工具建议删除或重建含数据的列
为什么发生
工具只比较结构差异,不了解现有数据能否安全转换或丢弃。
怎样纠正
逐行审查并在副本演练
误区 2

多人修改后重写历史

你会看到
不同环境拥有不一致迁移顺序
为什么发生
其他环境可能已经执行旧迁移,改写文件会让同一编号代表不同操作。
怎样纠正
已共享迁移通过新增文件修正
误区 3

上线时直接试迁移

你会看到
锁表或数据转换失败影响用户
为什么发生
生产数据量和并发与本地不同,锁表及转换耗时必须提前验证。
怎样纠正
先备份、演练并准备恢复步骤
04

HANDS-ON

动手任务

为任务模型生成一次可审查迁移,在练习库应用并回查结构与数据。

准备条件
  • 完成 6.2「SQL 与关系型数据库直觉」

跟着做

  1. 01

    安装并初始化 Prisma,连接本地 PostgreSQL。

  2. 02

    定义 User、Task 及一对多关系。

  3. 03

    生成第一份迁移并阅读 SQL。

  4. 04

    写 seed 或脚本创建一名用户与任务。

  5. 05

    用 Prisma Client 完成创建、查询、更新并核对数据库。

完成标志

为任务模型生成一次可审查迁移,在练习库应用并回查结构与数据。

加餐挑战

新增 dueAt 可选字段,写出从可选到必填的两阶段迁移计划。

离开本课前,自问四件事

  • ORM、Schema、生成客户端与数据库分别承担什么?
  • 关系加载为什么要按用例选择而不是默认全部取得?
  • 给有旧数据的表新增必填字段应怎样分阶段?
  • 为什么应用代码回滚并不保证数据库也能回到原状态?
完成本课了吗?

确认完成后,会同步更新学习中心的课程学习进度。