初始化数据
如何在数据库迁移过程中 初始化数据(Seeding Data) 。当你建好表后,通常需要塞入一些初始数据(如默认管理员、配置项等)。
1. 数据初始化 (Seeding Data) 的三种方式
- 使用 ActiveModel 初始化 : 借用已经定义好的 Rust 实体类来插入数据,具有最强的类型安全性:
let db = manager.get_connection();
cake::ActiveModel {
name: Set(
"Cheesecake".to_owned()),
..Default::default()
}
.insert(db)
.await?;
- 使用 SeaQuery 语句初始化 : 不需要依赖具体的实体类,直接通过代码构造插入语句,适合在实体类尚未生成时使用, eg:
let stmt = Query::insert()
.into_table("cake")
.columns(["name"])
.values_panic(["Tiramisu".into()])
.to_owned();
manager.execute(&stmt).await?;
- 事务式初始化 (Transactional) : 手动开启一个事务,确保数据插入要么全部成功,要么全部回滚,保证数据的一致性, eg:
let db = manager.get_connection();
let txn = db.begin().await?; // 开启事务
cake::ActiveModel {
name: Set("Cheesecake".to_owned()),
..Default::default()
}
.insert(&txn)
.await?;
txn.commit().await?; // 提交事务
2. 深度细节解析
① 为什么使用 ActiveModel?
这是最推荐的方式。因为它是强类型的,如果你的数据库字段改了,这段代码在编译阶段就会报错,而不是等到运行时才崩溃。
注意 :这要求你的
migrationcrate 能够引用到entitycrate。
② 为什么使用 SeaQuery?
如果你在写迁移脚本时,还没生成对应的 entity 代码,或者不想让迁移脚本和业务代码耦合得太深,就可以用 Query::insert()。它直接操作字符串表名和列名,灵活性更高。
③ 关于 PostgreSQL 的事务 (Important!)
你使用的是 PostgreSQL ,有一个非常大的优势:
- 自动事务 :SeaORM 在 Postgres 上运行
up函数时,默认会把整个函数包裹在一个事务里。 - 手动事务的作用 :虽然有自动事务,但文档中的
db.begin()允许你在迁移逻辑内部进行更细粒度的控制,或者在复杂的逻辑中明确标注事务边界。
3. 核心 API 说明
manager.get_connection(): 从迁移管理器中获取当前的数据库连接对象 (DbConn)。Query::insert(): SeaQuery 的插入语句构造器。manager.execute(&stmt): 执行构造好的 SeaQuery 语句。db.begin(): 在当前连接上开启一个异步事务。txn.commit(): 提交事务,让所有更改永久生效。
迁移脚本不只是能改“结构(表)”,还能改“内容(数据)”。在 PostgreSQL 中,利用其原子性特点,结合 ActiveModel 的类型安全,你可以非常稳健地完成数据库的初始化。