写入
读出来的是 Model,写进去的是 ActiveModel。ActiveModel 的每个字段是一个 ActiveValue:Set(要写)、Unchanged(读来的、没改)、NotSet(不写)。sea-orm 的写入都是从这三态出发,决定 INSERT 写哪几列、UPDATE 的 SET 有哪几项,再交给 sea-query 写成 SQL,经过和查询一样的 build → sqlx::query_with → acquire 发出去。相关源码:src/entity/active_value.rs 642 行、active_model.rs 2.6k(前一半是 ActiveModelTrait)、query/insert.rs 910、executor/insert.rs 610、query/update.rs + executor/update.rs 约 800、query/delete.rs + executor/delete.rs 约 540,大半是文档注释和测试。
- ActiveValue 与 ActiveModel:三态各自在
INSERT/UPDATE里的意义;set_ne只在新值等于Unchanged的旧值时保持不变,reset把Unchanged变成Set;into_active_model得到全Unchanged;from_json按 JSON 里有没有这个键决定Set还是NotSet。 - insert:
Set和Unchanged都会写进INSERT;exec只RETURNING主键,exec_with_returning拿回整行;insert_many里某一行没设的列被补成 NULL 而不是默认值;空列表在 2.0 里不发 SQL,1.1.20 会发VALUES (DEFAULT);on_conflict的DO NOTHING冲突时exec报RecordNotInserted,TryInsert给Conflicted,但exec_with_returning给的是RecordNotFound。 - update 与 delete:
update只SET被Set的非主键列,主键只进WHERE;一列都没Set时不发UPDATE,只按主键SELECT一次;没匹配到行报None of the records are updated;主键NotSet在 2.0 是PrimaryKeyNotSet,1.1.20 是 panic;update_many/delete_many和delete_by_id的返回类型。 - save 与 ActiveModelBehavior:
save看主键有没有NotSet决定 insert 还是 update;四个钩子拿到什么,哪些写入路径不走钩子。 - 嵌套写入 ActiveModelEx:2.0 的 builder 一次写一棵关联对象,按外键依赖排顺序。
flowchart TB model[Model] -->|into_active_model| am["ActiveModel 全 Unchanged"] am -->|"Set / set_ne"| am2["ActiveModel 部分 Set"] am2 --> ins["Insert 写 Set 和 Unchanged"] am2 --> upd["UpdateOne 只 SET 被 Set 的列"] am2 --> del["DeleteOne 只用主键"] ins --> ret["RETURNING 拿回整行"] upd --> ret ret --> model
save 和钩子只是在上面这三条路前后各加一步,insert / update 的 SQL 由前三页讲清。语句怎么写成 $N 和参数在 QueryBuilder 与参数,DbErr 各分支的全貌在错误,写入要放进事务时看事务。
💬 关联讨论
发起讨论加载中...