Wasp 0.13 教程:用 Prisma PSL 定义数据库 Entity,从 Task 模型到数据库迁移
【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp
本篇技术指南基于 Wasp 官方文档 0.13 版教程第 4 节 04-entities.md,讲解如何在 Wasp 应用中定义数据库 Entity(以 Todo App 的Task模型为例):从在 Wasp 文件里用{=psl}标签书写 Prisma Schema Language(PSL)、执行wasp db migrate-dev生成并应用数据库迁移,到用wasp db studio可视化检查数据。读完后你能够独立完成“声明 Entity → 同步数据库结构 → 验证表结构”这一完整数据建模闭环,并理解 Wasp Entity 与 Prisma 模型之间 1:1 对应的底层机制。需要说明的是:本文对应 Wasp 0.13 的教程版本,当时应用定义写在main.wasp文件中;当前仓库中的示例(如examples/tutorials/TodoApp)已演进为 TypeScript Spec(main.wasp.ts),文末会给出两者的对照。
Entity:Wasp 数据模型的基石
Entity 是 Wasp 最核心的概念之一,用于定义“哪些数据会存入数据库”。每一条entity声明与 Prisma 数据模型(Prisma model)一一对应:Wasp 底层使用 Prisma ORM 实现全部数据库功能,Entity 声明只是它之上的一层薄抽象。
这意味着你定义 Entity 的唯一前置技能是熟悉Prisma Schema Language(PSL)——一种为声明数据模型而设计的、直观且声明式的语言。你不需要先深入掌握 Prisma 的完整用法,因为 Wasp 为 Prisma 的核心能力提供了简单的 API 封装(详见 Entities 参考文档)。
在 Wasp 文件中定义 Task Entity
Todo App 围绕“任务”展开,因此教程在main.wasp中新增一个Taskentity 声明:
// ... entity Task {=psl id Int @id @default(autoincrement()) description String isDone Boolean @default(false) psl=}逐段拆解这条声明:
entity Task—— 告诉 Wasp 要定义一个名为Task的 Entity(即数据库模型)。Wasp 会自动创建一张名为tasks的表。{=psl ... psl=}—— 两个psl标签之间的所有内容,Wasp 都按 PSL 解析。这体现了 Wasp “用标签嵌入 DSL” 的文件组织方式:Wasp 自身的声明语法和 Prisma 的 PSL 共存于同一文件中,各归其位。
PSL 部分定义了tasks表的三列:
| 字段 | 类型 | 注解 | 语义 |
|---|---|---|---|
id | Int | @id @default(autoincrement()) | 主键,由数据库自增自动生成 |
description | String | 无 | 任务描述文本,创建时必填 |
isDone | Boolean | @default(false) | 完成状态;创建时若不显式赋值,数据库自动写入false |
其中@id标记主键,@default(autoincrement())让整数主键在前一个最大值上自增,@default(false)是字段级默认值——三者都是 PSL 中最常用的注解。
底层机制:Entity 声明如何变成 Prisma 模型
Wasp 的生成流程会把你写在{=psl}标签内的内容直接落入项目根目录的schema.prisma,从而驱动 Prisma Client 的生成与迁移。教程配套的自动化补丁文件 04-entities__prisma-task.patch 展示了这一步的确切结果——在已有的datasource与generator块之后追加:
model Task { id Int @id @default(autoincrement()) description String isDone Boolean @default(false) }可以看到entity Task {=psl ... psl=}中的 PSL 内容与schema.prisma中model Task { ... }的花括号内内容完全一致,只是外层的entity关键字换成了 Prisma 的model关键字。当前仓库的 TodoApp 示例 schema.prisma 也印证了这一点:Task模型的三个字段与教程声明逐字对应,仅在此后加入认证功能时追加了与User的关联字段(user User? @relation(...)和userId Int?)。
同步数据库结构:wasp db migrate-dev
声明 Entity 之后,必须让数据库的实际结构跟上声明。教程给出的操作流程是:
- 若
wasp start进程正在运行,先将其停止; - 执行:
wasp db migrate-dev任何时候修改了 Entity 定义,都要重复这一步。该命令指示 Prisma 创建一个新的数据库迁移脚本,并将其应用到数据库上。迁移脚本会自动放入项目根目录的migrations/文件夹——Entities 参考文档 特别强调:这个文件夹应当提交进版本控制,因为它是数据库结构演化的历史记录。
从 CLI 源码结构看,wasp db子命令的实现集中在 Db.hs,migrate-dev与studio等子命令在此处注册并分发,最终委托给 Prisma 的 CLI 能力完成迁移与数据浏览。
查看数据库:wasp db studio
迁移完成后,运行:
wasp db studio这会在浏览器中打开一个新页面(Prisma Studio),供你查看和编辑数据库中的数据。在 0.13 教程的配图中,页面左侧列出了刚生成的Task表,点击该表即可看到id、description、isDone三列的定义。此时数据库里还没有任何行数据——“即将改变这一点”的正是教程的后续章节。
Entity 的后续用法:Operations 与 Prisma Client
定义了 Entity 只是数据建模的第一步,参考文档(Entities)给出了 Entity 的完整使用路径:
- 在 Wasp 文件中创建/更新 Entity;
- 运行
wasp db migrate-dev同步数据库模型,迁移脚本落入migrations/并提交; - 在实现 Operations(Query 与 Action)时通过 Wasp 的 JS API 访问数据库。
在 Operations 中使用 Entity是最常见的方式。以教程下一步的getTasksQuery 为例:在 Wasp 文件的query声明中通过entities: [Task]声明依赖Taskentity 后,Wasp 会在 Query 函数的context中注入Task的 Prisma client,实现里直接调用:
export const getTasks = async (args, context) => { return context.entities.Task.findMany({ orderBy: { id: 'asc' }, }) }直接使用 Prisma Client则是需要更细粒度控制时的兜底方案:Prisma Client 只能用在 Wasp 的服务端代码中,导入方式为:
import { prisma } from 'wasp/server' prisma.task.create({ description: "Read the Entities doc", isDone: true })官方建议优先使用 Wasp 提供的惯用机制,只有在 Wasp 未覆盖你的需求时才直接使用 Prisma Client。
版本演进对照:从 main.wasp 到 main.wasp.ts
需要注意的适用前提:本文对应 0.13 版教程,当时应用定义写在main.wasp文件中,Query/Action 以query getTasks { fn: import { getTasks } from "@src/queries", entities: [Task] }的形式声明。当前仓库的示例已迁移到 TypeScript Spec 写法,TodoApp 的 main.wasp.ts 中,同样的“声明操作依赖 Task 实体”变成了显式的配置参数:
spec: [ query(getTasks, { entities: ["Task"] }), action(createTask, { entities: ["Task"] }), action(updateTask, { entities: ["Task"] }), ],entities字段的语义保持一致:告诉 Wasp 该操作读写了哪些 Entity,从而注入对应的 Prisma client,并让 Wasp 在数据变更时自动刷新相关 Query 的客户端缓存。数据建模的核心工作流——PSL 定义 Entity、wasp db migrate-dev迁移、wasp db studio验证——在两个版本间保持不变。
小结
- Entity 声明与 Prisma model 一一对应,PSL 写在
{=psl psl=}标签内,Wasp 自动建表(Task→tasks表); - 每次修改 Entity 定义后必须运行
wasp db migrate-dev,迁移脚本生成于migrations/目录并提交版本控制; wasp db studio提供浏览器内数据查看与编辑,是验证表结构的直观手段;- Entity 主要经由 Operations 的
context.entities.X访问,必要时在服务端代码直接import { prisma } from 'wasp/server'。
掌握以上内容后,下一步自然衔接教程第 5 节“Querying the Database”(05-queries.md),把刚建好的Task表真正读写起来。
【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考