一句话:Entity 文件就是数据表的完全表达。 打开一个 entity 文件,不需要连数据库、不需要看 DDL,就能知道这张表的一切。
数据表特性Rust 写法说明NOT NULLpub name: String不写 Option = NOT NULL,SeaORM 建表时自动加约束可为 NULLpub name: Option<String>编译器强制处理 None枚举字段pub status: MyEnum用 Rust enum + DeriveActiveEnum。 禁止用 StringJSON 字段pub config: MyStruct用强类型 struct + FromJsonQueryResult。 禁止用 String 或 serde_json::Value(结构不固定时除外)时间字段pub created_at: DateTimeUtc禁止用 NaiveDateTime,统一 UTC默认值#[sea_orm(default_value = "xxx")]注解标注,SeaORM 建表时自动加 DEFAULT主键#[sea_orm(primary_key)]唯一约束#[sea_orm(unique)]索引#[sea_orm(indexed)]
有状态流转的枚举,必须实现 can_transition_to() 方法,状态变更前必须调用。
rust
impl OrderStatus {
pub fn can_transition_to(&self, next: &OrderStatus) -> bool {
matches!((self, next),
(OrderStatus::Draft, OrderStatus::Active)
| (OrderStatus::Active, OrderStatus::Archived)
)
}
}
member_level.max_borrows())rust
db.transaction::<_, ResultType, ErrType>(|txn| {
Box::pin(async move {
// 所有操作共享 txn,出错自动 rollback
Ok(result)
})
}).await?;
使用软删除( is_deleted: bool)的表,查询活跃记录时必须带 .filter(Column::IsDeleted.eq(false))。除非明确需要查全量(注释说明原因)。
//! doc comment:业务规则、状态流转、软删除约定、关联关系等/// 注释:业务含义,不只是字段名的复述使用 SeaORM 2.0 Entity First,entity 就是数据库 schema 的唯一事实源:
rust
let db = Database::connect(db_url).await?;
db.get_schema_registry("my_crate::entity::*").sync(db).await?;
#[sea_orm(renamed_from = "old_name")] 自动 RENAME以下不是强制要求,根据项目规模和需要决定:
Relation enum):需要关联查询(JOIN/预加载)时添加impl Model { fn new_xxx() }):有动态默认值(如"可借数量 = 总数量")时添加,让创建逻辑集中在 entity 文件impl Entity { async fn find_xxx() }):同一段查询逻辑重复使用时提取String 存枚举值String 或 serde_json::Value 存结构化 JSONNaiveDateTimecan_transition_to()can_transition_to() 方法参考 references/ENTITY_EXAMPLE.md 获取完整示例。
references/check_db_contracts.sh 可集成到 CI,自动检查以上规则。
bash
# 用法
./check_db_contracts.sh [src_dir] # 默认 ./src
# 集成到 CI
cargo build && ./check_db_contracts.sh
检测项:
.set(ActiveModel) 替代)serde_json::Value 或 NaiveDateTimecan_transition_to() 检查is_deleted错误(❌)会导致脚本返回非零退出码(CI 失败),警告(⚠)不阻断。