Wasp 数据库后端实战指南:SQLite / PostgreSQL 的连接、迁移与数据播种
2026/9/15 3:03:26 网站建设 项目流程

Wasp 数据库后端实战指南:SQLite / PostgreSQL 的连接、迁移与数据播种

【免费下载链接】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(v0.14 时代文档体系)的数据层为背景,系统讲解 Wasp 项目如何选择数据库后端、如何连接开发数据库、如何从 SQLite 平滑迁移到 PostgreSQL,以及如何使用app.db.seeds编写并执行数据库播种(seeding)函数。读完本文,你将掌握 Wasp 中数据库配置的完整链路——从schema.prismaprovider切换、DATABASE_URL环境变量的注入方式,到wasp db系列命令的实际用法,并理解其底层(AppSpec Db 定义 与 Seed 生成器)是如何工作的。

数据库在 Wasp 数据层中的位置

在 Wasp 中,Entities、Operations 与 Automatic CRUD 共同构成了操作应用数据的高层接口:Entities 定义数据模型,Operations 声明查询与操作,Automatic CRUD 则自动生成常见的增删改查接口。但无论接口多高,数据最终都要落到某个存储介质上——这就是数据库后端要解决的问题。

Wasp 把数据库抽象为两部分:

  • schema.prisma文件:遵循 Prisma 的 datasource 语法,声明数据库provider和连接url
  • app.db配置(写在main.wasp中):声明播种函数等数据库相关能力。

两条线索最终都会在编译阶段被 Wasp 读取并生成对应的服务端代码,因此理解二者的关系是掌握 Wasp 数据库用法的前提。

支持的数据库后端

Wasp 在 AppSpec 的 Db 模块中把数据库系统建模为枚举DbSystem = PostgreSQL | SQLite,即官方支持且经过代码路径校验的后端只有两个:SQLite 与 PostgreSQL。下面分别说明。

SQLite:默认的开发数据库

当你通过wasp new创建新项目时,生成器会写出以 SQLite 为默认 provider 的schema.prisma(见 basic 模板 与 minimal 模板):

datasource db { provider = "sqlite" url = env("DATABASE_URL") } // ...

使用 SQLite 时,Wasp 会自动为你设置DATABASE_URL环境变量,你不需要准备任何数据库服务、不需要 Docker、不需要安装额外的中间件。这正是它适合快速起步的原因。

但需要注意它的边界:SQLite 只能用于开发阶段。一旦你要把 Wasp 应用部署到生产环境,就必须切换到 PostgreSQL,并且之后保持使用 PostgreSQL(Wasp 不会在生产环境替你管理 SQLite)。好在迁移过程并不复杂,本文后续有专门的迁移章节指导你完成切换。

PostgreSQL:面向生产的选择

PostgreSQL 是一款在开源数据库领域久经考验的成熟产品,适合对稳定性、并发和特性有更高要求的应用。在 Wasp 中使用 PostgreSQL 同样简单,只需把schema.prisma中的 provider 改为"postgresql"

datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ...

一旦切换到 PostgreSQL,你必须在开发期间保证有一个数据库实例在运行——Wasp 执行wasp startwasp db migrate-dev等命令时都需要真实可用的数据库连接。至于如何提供这个连接,请看下一节。

仓库中的示例项目可以印证这一点:例如 ask-the-documents 的 schema.prisma 就是一个真实使用 PostgreSQL 的案例,它还额外启用了pgvector扩展来存储向量字段,这说明schema.prisma中 Prisma 支持的能力(扩展、生成器等)在 Wasp 中都可以正常使用。

连接数据库

使用 SQLite:零配置

如果你使用 SQLite,连接工作完全由 Wasp 接管,无需任何额外操作。DATABASE_URL由 Wasp 在启动时注入,你只需要正常执行wasp start即可。

使用 PostgreSQL:两种连接方式

使用 PostgreSQL 时,Wasp 提供两种连接策略:

  1. 托管式体验:让 Wasp 帮你启动一个开箱即用的开发数据库;
  2. 自主控制:你自己准备数据库,通过DATABASE_URL连接串告诉 Wasp。
方式一:使用 Wasp 提供的开发数据库

执行下面的命令,Wasp 会为你启动一个默认的 PostgreSQL 开发数据库:

wasp start db

Wasp 应用会自动连接上它,只需让wasp start db在后台保持运行。使用前请确认:

  • 本机已安装 Docker 且docker命令在PATH中可用(wasp start db正是通过 Docker 拉起 PostgreSQL 容器);
  • 端口5432没有被其他进程占用。

提示:如果你希望通过psql、pgAdmin 等外部工具连接这个开发数据库,运行wasp db start时控制台最开头打印的就是它的连接凭据。

方式二:连接已有的数据库

如果你想自建开发数据库,或连接外部(如远端)数据库,通过DATABASE_URL环境变量告知 Wasp 即可,Wasp 会把它当作连接串直接使用。

最简单的做法是把DATABASE_URL写进项目根目录的 .env.server 文件(该文件不存在则新建):

DATABASE_URL=postgresql://user:password@localhost:5432/mydb

也可以在执行wasp命令时以内联方式注入(对所有环境变量均适用):

DATABASE_URL=<my-db-url> wasp ...

这个技巧非常适合针对特定数据库执行某条命令。例如对全新的 staging 或 production 数据库做初始化播种:

DATABASE_URL=<production-db-url> wasp db seed myProductionSeed

上述命令会把种子数据写入目标生产/预发布数据库——这正是「播种」最常见的生产场景之一,更多细节见播种数据库一节。

从 SQLite 迁移到 PostgreSQL

要把应用带上生产环境,你需要完成 SQLite → PostgreSQL 的切换。Wasp 给出的迁移步骤很直接:

第 1 步:切换 provider

schema.prisma中的 provider 改为"postgresql"

datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ...

第 2 步:清掉旧的迁移与旧数据库

旧迁移文件是面向 SQLite 生成的,无法用于 PostgreSQL,SQLite 数据库文件本身也不再需要。删除迁移目录后,用wasp clean清理生成产物:

rm -r migrations/ wasp clean

第 3 步:确保新数据库在运行

参考连接数据库一节,启动 PostgreSQL(可以用wasp start db,也可以自己准备并设置好DATABASE_URL)。让它在后台保持运行,因为下一步需要它。

第 4 步:生成初始迁移

在另一个终端中执行:

wasp db migrate-dev

Wasp 会连接你正在运行的 PostgreSQL,把当前 schema 应用到数据库并生成一份全新的初始迁移。

第 5 步:完成

至此迁移结束。此后项目将一直以 PostgreSQL 为数据库后端,schema.prisma的新改动继续通过wasp db migrate-dev管理。

播种数据库

**数据库播种(database seeding)**指的是向数据库填充初始数据的过程。最常见的两种用途:

  1. 把开发数据库置入一个方便开发与测试的状态;
  2. 为任意环境(dev / staging / prod)的数据库初始化其运转所必需的基准数据,例如向 Currency 表填充默认币种、向 Country 表填充全部国家。

编写 Seed 函数

main.wasp中,你可以在app.db.seeds字段下以数组形式声明任意多个seed 函数

app MyApp { // ... db: { seeds: [ import { devSeedSimple } from "@src/dbSeeds.js", import { prodSeed } from "@src/dbSeeds.js" ] } }

如果你使用的是新版 TypeScript 规范(main.wasp.ts),同样的声明方式见 kitchen-sink 示例中的 db 配置,它同时展示了seedsprismaSetupFn两个字段的写法。

每个 seed 函数必须是接收一个参数的 async 函数,该参数prisma是用于操作数据库的 Prisma Client 实例——这个实例与 Wasp 内部使用的完全一致

由于 seed 函数属于服务端代码,它天然可以导入其他服务端函数。这意味着你可以很方便地「用 Action 来播种」——例如下面的例子,seed 函数同时创建了一个带用户名密码的用户,并调用createTask这个 Action 为用户创建任务:

import { createTask } from './actions.js' import { sanitizeAndSerializeProviderData } from 'wasp/server/auth' export const devSeedSimple = async (prisma) => { const user = await createUser(prisma, { username: 'RiuTheDog', password: 'bark1234', }) await createTask( { description: 'Chase the cat' }, { user, entities: { Task: prisma.task } } ) } async function createUser(prisma, data) { const newUser = await prisma.user.create({ data: { auth: { create: { identities: { create: { providerName: 'username', providerUserId: data.username, providerData: sanitizeAndSerializeProviderData({ hashedPassword: data.password }), }, }, }, }, }, }) return newUser }

代码中有两点值得注意:

  • 创建用户时直接操作prisma.user,并在auth.identities中写入providerName: 'username'的身份数据,hashedPassword经过sanitizeAndSerializeProviderData序列化——这与 Wasp 内部创建用户名密码登录身份的实现一致;
  • createTask的第二个参数携带{ user, entities: { Task: prisma.task } },这是 Wasp Action 执行上下文(context)的标准形态,说明 seed 完全可以复用应用中已有的操作逻辑。

TypeScript 版本使用DbSeedFn类型标注 seed 函数:

import { createTask } from './actions.js' import { type DbSeedFn } from 'wasp/server' import { sanitizeAndSerializeProviderData } from 'wasp/server/auth' import { type AuthUser } from 'wasp/auth' import { PrismaClient } from '@prisma/client' export const devSeedSimple: DbSeedFn = async (prisma) => { const user = await createUser(prisma, { username: 'RiuTheDog', password: 'bark1234', }) await createTask( { description: 'Chase the cat', isDone: false }, { user, entities: { Task: prisma.task } } ) }; async function createUser( prisma: PrismaClient, data: { username: string, password: string } ): Promise<AuthUser> { const newUser = await prisma.user.create({ data: { auth: { create: { identities: { create: { providerName: 'username', providerUserId: data.username, providerData: sanitizeAndSerializeProviderData<'username'>({ hashedPassword: data.password }), }, }, }, }, }, }) return newUser }

DbSeedFn由 Wasp 导出,其定义如下:

type DbSeedFn = (prisma: PrismaClient) => Promise<void>

devSeedSimple标注该类型后,TypeScript 会得到两重保证:

  • seed 函数的参数prisma类型为PrismaClient
  • seed 函数的返回值类型为Promise<void>

仓库中的真实范例可以参考 kitchen-sink 的 seeds.ts:它同时导出了devSeedSimpleprodSeed两个 seed 函数,分别向开发库与生产库写入用户名、任务等初始数据,并打印日志确认执行结果——与本文示例模式完全一致。

运行 Seed 函数

运行命令:

wasp db seed

如果你定义了多个 seed 函数,Wasp 会以交互方式让你选择运行哪一个;只定义了一个则会直接运行。

也可以直接指定名称执行:

wasp db seed devSeedSimple

实用技巧:在wasp db reset清空数据库之后,紧接着运行wasp db seed把初始数据填回去,是开发中最常见的组合操作。

API 参考:app.db 与种子命令

app.db 配置项

app.db是一个字典,所有字段均为可选:

app MyApp { title: "My app", // ... db: { seeds: [ import devSeed from "@src/dbSeeds.js" ], } }
  • seeds: [ExtImport]定义可用wasp db seed命令执行的 seed 函数列表,用于向数据库填充初始数据。每个元素是一个外部导入(ExtImport),指向@src/下的服务端模块。完整的语义见播种数据库一节。

从源码实现看,AppSpec 的 Db 记录除了seeds外还定义了prismaSetupFn字段——后者用于注入自定义的 Prisma 初始化逻辑(如示例中的setUpPrisma),说明app.db在设计上就是围绕 Prisma 生态的可扩展配置入口。

CLI 命令

  • wasp db seed:只定义一个 seed 函数时直接运行它;定义多个时以交互方式让你选择。

  • wasp db seed <seed-name>:直接运行指定名称的 seed 函数。该名称就是它在app.db.seeds列表的import表达式中的标识符。例如对如下声明:

    app MyApp { // ... db: { seeds: [ // ... import { devSeedSimple } from "@src/dbSeeds.js", ] } }

    运行:

    wasp db seed devSeedSimple

源码视角:db 命令与种子生成的底层机制

理解 Wasp 是如何执行这些命令的,有助于排查问题。

db 命令的公共前置流程。在 CLI 的 Db 模块中,所有wasp db ...命令都经由makeDbCommand包装,它依次完成:

  1. 校验当前目录是 Wasp 项目(InWaspProject);
  2. 校验 Wasp 规范文件可用(WaspSpecAvailable);
  3. 执行编译并安装 npm 依赖(compileWithOptions,即代码生成阶段);
  4. 校验数据库连接已建立(DbConnectionEstablished)。

这正是文档中「Wasp 需要访问你的数据库才能执行wasp startwasp db migrate-dev」这一说法的代码依据——任何 db 命令的前提都是「先编译出代码、再连上数据库」。

种子脚本的生成。在代码生成阶段,Seed 生成器读取 AppSpec 中的seeds列表,为服务端生成dbSeed.ts脚本,并把每个 ExtImport 转换为可注入的导入;当存在至少一个 seed 时,它还会在package.json的 Prisma 配置中注册prisma.seed = "npm run db-seed"getPackageJsonPrismaSeedField),从而让 Prisma 层面的 seed 机制与 Wasp 的 seed 命令打通。此外,它还定义了环境变量名WASP_DB_SEED_NAME(见 Seed.hs)——wasp db seed <name>正是通过向该环境变量写入指定名称,再由生成的脚本据此挑选并执行对应的 seed 函数。

小结

围绕 Wasp 的数据库能力,你需要记住四条主线:

  1. 默认 SQLite、生产 PostgreSQL:新项目开箱即用 SQLite(零配置、仅限开发),上线前务必切换到 PostgreSQL;
  2. 连接方式二选一wasp start db走 Docker 拉起托管开发库,或通过.env.server/ 命令行内联注入DATABASE_URL连接自建库;
  3. 迁移三步走:改 provider →rm -r migrations/+wasp clean→ 确保 PG 运行后wasp db migrate-dev
  4. 播种即服务端函数:在app.db.seeds中声明任意多个(prisma) => Promise<void>函数(推荐用DbSeedFn标注类型),用wasp db seed [name]执行,可用于初始化 dev / staging / prod 任意环境的基准数据。

把上述操作与 AppSpec Db 定义、Seed 生成器 及 kitchen-sink 示例 对照阅读,你就能在 Wasp 中自如地管理从开发到生产的完整数据链路。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询