feat: 新增数据填充 seed 命令(@Seed 宏自动注册,不记录运行历史)、database truncate/drop、打包只读模式,提示统一为 simcu::orm,版本 1.2.0
This commit is contained in:
@@ -212,8 +212,13 @@ main(args: Array<String>) {
|
||||
| `cjpm run -- orm update` | 连接数据库,按 `migrationId` 字典序应用所有未执行的迁移 |
|
||||
| `cjpm run -- orm downgrade [目标]` | 回退迁移:无目标=回退最近一个;有目标=回退到该迁移之后(含该迁移的 down) |
|
||||
| `cjpm run -- orm list` | 列出已注册迁移(需真实连接读取历史表) |
|
||||
| `cjpm run -- orm seed` | 列出数据填充;`seed <id>` 运行指定;`seed --all` 运行全部(见「数据填充」) |
|
||||
| `cjpm run -- orm database truncate` | 清空所有业务表数据(保留表结构与迁移历史) |
|
||||
| `cjpm run -- orm database drop` | 删除所有表(含迁移历史),完全清空数据库,之后 `update` 可重建 |
|
||||
| `cjpm run -- orm help` | 显示帮助 |
|
||||
|
||||
**开发/部署模式**:在项目目录(含 `cjpm.toml`)通过 `cjpm run` 运行时全部命令可用;打包部署后(工作目录无 `cjpm.toml`)自动进入只读模式,仅保留 `list` / `update`(应用迁移)/ `seed`(数据填充,只写业务数据)。
|
||||
|
||||
**生成约定**:
|
||||
- **首次使用(无迁移)**:不需要建 `src/migrations/` 目录,也不要写 `import <应用包名>.migrations.*`(该子包不存在会导致编译失败);首次 `add` 时 CLI 自动创建目录并生成迁移文件 + 注册文件;
|
||||
- **生成后手动加 import**:执行 `add` 生成首个迁移后,在 `main()` 所在文件手动加一行 `import <应用包名>.migrations.*`(如 `import myapp.migrations.*`)——注册文件在子包内惰性加载,只有 import 触发后 `update/downgrade/list` 才能看到迁移;之后新增迁移无需再动这行;
|
||||
@@ -222,6 +227,41 @@ main(args: Array<String>) {
|
||||
- 快照持久化在 `src/migrations/snapshot.json`;`add` 用「旧快照 vs 当前模型」做 diff,所以**改模型后重新编译应用再 `add`** 即生成增量迁移;
|
||||
- 生成源码文本已包含 `import std.collection.*` 等标准库引用,应用无需额外配置。
|
||||
|
||||
### 数据填充(Seed)
|
||||
|
||||
`orm seed` 提供数据填充:用 `@Seed` 类级宏标注普通类,`run(ctx)` 内用**应用自己的 DbContext** 直接操作 ORM。**无需注册表、不记录运行历史,可随时/多次运行,幂等由填充代码自行保证**(如按 id find 后不存在再插入)。
|
||||
|
||||
```cangjie
|
||||
// src/seeds/InitGames.cj
|
||||
import simcu::orm.macros.*
|
||||
import simcu::orm.seeds.*
|
||||
import myapp.models.*
|
||||
|
||||
@Seed["初始化游戏服务器配置"] // seedId 取类名 InitGames,参数仅作描述
|
||||
public class InitGames {
|
||||
public func run(ctx: MyDbContext): Unit {
|
||||
if (ctx.games.find("game-1").isNone()) { // 自行保证幂等
|
||||
let g = Game()
|
||||
g.id = "game-1"
|
||||
g.apiKey = "dev-key-1"
|
||||
g.name = "测试服"
|
||||
ctx.games.add(g)
|
||||
ctx.saveChanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`@Seed` 宏在编译期自动展开:生成包装类(继承 `simcu::orm.seeds.Seed`,把 `ctx` 从 `Any` 转型为 run 参数类型后调用)和顶层 `let registerSeed(...)`,模块加载即自动注册,**无需手写注册文件**。应用侧只需在 `main()` 所在文件加一行 `import <应用包名>.seeds.*` 触发子包加载(与迁移注册文件同模式)。
|
||||
|
||||
| 命令 | 作用 |
|
||||
|------|------|
|
||||
| `cjpm run -- orm seed` | 列出全部已注册填充(seedId + 描述) |
|
||||
| `cjpm run -- orm seed <id>` | 运行指定填充(支持唯一前缀匹配) |
|
||||
| `cjpm run -- orm seed --all` | 依次运行全部填充(单个失败继续执行其余,最终非零退出) |
|
||||
|
||||
> 运行前自动检查迁移是否全部已应用(避免目标表不存在);打包环境同样可用。
|
||||
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
@@ -232,7 +272,8 @@ orm-cj/
|
||||
├── src/
|
||||
│ ├── Orm.cj # 聚合导出:import simcu::orm.* 即全部可见
|
||||
│ ├── annotations/ # @Table / @Column / @Key / @AutoIncrement / @Ignore / @Required / @MaxLength
|
||||
│ ├── macros/ # @DbContext 类级宏(纯声明 DbSet 类 → 完整 DbContext 子类)
|
||||
│ ├── macros/ # @DbContext 类级宏 + @Seed 数据填充宏(自动注册,无需手写注册表)
|
||||
│ ├── seeds/ # Seed 基类 + 进程级填充注册表(registerSeed / allSeeds)
|
||||
│ ├── model/ # EntityModel(反射映射)、ModelCache(模型缓存)、
|
||||
│ │ # ColumnNamingPolicy(列命名策略)、ValueReader、ParamBinder、GuidUtil
|
||||
│ ├── tracking/ # ChangeTracker(操作队列)、EntityState、EntityEntry
|
||||
@@ -240,7 +281,7 @@ orm-cj/
|
||||
│ │ # OpenGaussDialect(继承 PG)、ColumnTypes(列类型)
|
||||
│ ├── query/ # QueryBuilder<T>(条件/排序/分页)、PagedResult<T>
|
||||
│ ├── db/ # DbContext(连接 + 提交 + 物化 + 数据库存在性/迁移状态检查)、DbSet<T>
|
||||
│ ├── cli/ # MigrationCli(add/rm/update/downgrade/list 命令)、
|
||||
│ ├── cli/ # MigrationCli(add/rm/update/downgrade/list/seed/database 命令)、
|
||||
│ │ # MigrationFileGenerator(迁移/注册文件源码生成)
|
||||
│ ├── migrations/ # Migration 基类、MigrationBuilder、ColumnDefinition、
|
||||
│ │ # DdlFactory(操作 → DDL SQL,差异语法委托方言)、
|
||||
@@ -369,6 +410,13 @@ qb.page(2, 10) // PagedResult<User>(items/total/
|
||||
- `ColumnTypes`(定义于 `simcu::orm.sql`):`BigIntCol`(openGauss 自增 → BIGSERIAL)/ `IntCol`(自增 → SERIAL)/ `SmallIntCol` / `TinyIntCol` / `TextCol`(VARCHAR,默认 255)/ `BoolCol` / `FloatCol`(DOUBLE PRECISION)/ `RealCol` / `DateTimeCol` / `DecimalCol`(DECIMAL(18,6))/ `BinaryCol`(BYTEA);实际 DDL 映射由方言 `columnTypeSql` 决定;
|
||||
- `Migrator`:`pending(migrations)` 预览未执行项;`migrate(migrations)` 事务内按 `migrationId` 字典序应用未执行项并写入历史表 `simcu_orm_migrations`。
|
||||
|
||||
### 6. 数据填充(@Seed 宏)
|
||||
|
||||
- `@Seed["描述"]` 标注普通类:**seedId 取类名**,属性参数仅作描述;类内 `run(ctx)` 用应用自己的 DbContext 直接增删改;
|
||||
- 宏自动生成 `Seed` 子类包装(`run(ctx: Any)` 内转型调用)+ 顶层 `let registerSeed(...)`,模块加载即注册,**无需手写注册表**;
|
||||
- 语义:**不记录运行历史**,可随时/多次运行,幂等由 `run` 内自行保证(如按 id find 后不存在再插入);
|
||||
- 应用侧需 `import <应用包名>.seeds.*` 触发子包加载(与迁移注册文件同模式);CLI 见「数据填充(Seed)」。`@Seed` 要求类提供单参数 `run(ctx)`,描述不能含双引号/反斜杠/换行。
|
||||
|
||||
---
|
||||
|
||||
## 运行测试
|
||||
|
||||
Reference in New Issue
Block a user