Rust in Everything
基于 sea-orm 2.0.4

实体

这一部分是定义主线:一个实体从你写下的 Model struct,到查询和写入时用到的那些 trait。相关源码在 src/entity/(约 1.2 万行,其中 base_entity.rs、column.rs、model.rs、primary_key.rs、identity.rs 是这一部分的前三章要读的)和 sea-orm-macros/src/derives/(entity_model.rs、model.rs、model_ex.rs、typed_column.rs 等)。sea-orm 自己几乎不定义「表」和「列」是什么:表和列都是 sea-query 的标识符(Iden),值是 sea-query 的 Value,条件是 sea-query 的 Expr。实体层做的事,是把这些无类型的积木挂到 Rust 类型上。

前三章讲一个实体本身:它由哪几个 trait 组成,宏为它生成了什么,它的列怎么变成条件、怎么把值读回来。后两章讲实体之间的关系和列上的自定义类型,由另外两页负责。

  1. 实体的几个 trait:Entity 是零大小的单元结构体,类型本身就是表;EntityTrait 用七个关联类型把 Model、Column、PrimaryKey、ActiveModel、Relation 以及 2.0 新增的 ModelEx、ActiveModelEx 串起来,find / insert / update / delete 都是默认方法;主键的 Rust 类型就是 find_by_id 的参数类型,复合主键是元组。
  2. DeriveEntityModel 与 dense 格式:一个三列的 Model 展开成约一千行;字段属性各落在哪段生成代码里;#[sea_orm::model] 不改动前一千行,只在后面追加 ModelEx、ActiveModelEx、TypedColumn / COLUMN、生成的 Relation、EntityLoader 和 builder(),两种写法对同一张表发出的 SQL 完全相同。
  3. 列与值:eq / is_in / contains / eq_any 各自变成什么 SQL 和参数;eq(None) 从 2.0 起是 IS NULL;强类型列 COLUMN.x 在编译期按值的类别检查,Column::X 收任何 Into<Value>;Value 每种类型一个带 Option 的分支;NULL 落进非 Option 字段时 2.0 报 Missing value for column。
  4. 关系:RelationDef、Related<T>、Linked,以及 dense 格式的 HasOne / HasMany / BelongsTo 字段。
  5. ActiveEnum 与 ValueType:Rust enum 和 newtype 怎么成为一列。
flowchart TB
  model["Model struct"] --> derive[DeriveEntityModel]
  derive --> entity["Entity 单元结构体"]
  derive --> column["Column 枚举"]
  derive --> pk["PrimaryKey 枚举"]
  derive --> am[ActiveModel]
  dense["sea_orm::model 属性"] --> ex["ModelEx / COLUMN / Loader"]
  column --> expr["sea-query Expr"]
  entity --> sel["Select E"]
  expr --> sel
  sel --> qr[QueryResult]
  qr -->|TryGetable| model

宏生成的 ActiveModel 和写入路径在 05 写入;Expr 怎么被写成 SQL 文本在 sea-query 的 QueryBuilder。

💬 关联讨论

发起讨论
加载中...