ActiveModel Operations (CUD)
Relevant source files
The following files were used as context for generating this wiki page:
ActiveModel is the primary mechanism in SeaORM for performing Create, Update, and Delete (CUD) operations. Unlike a standard Model, which represents a static row retrieved from the database, an ActiveModel tracks the state of individual fields using ActiveValue. This tracking allows SeaORM to construct efficient SQL queries that only target modified columns, avoiding race conditions and unnecessary data transmission.
Sources: sea-orm-sync/src/entity/active_model.rs:13-22, CLAUDE.md:126-128
Core Components and State Management
The behavior of CUD operations is governed by the state of ActiveValue for each field in the model.
ActiveValue States
| State | Description | SQL Impact |
|---|---|---|
Set(V) | The value has been explicitly assigned. | Included in INSERT or UPDATE statements. |
Unchanged(V) | The value was loaded from the database and not modified. | Ignored in UPDATE; included in INSERT if not null. |
NotSet | The value is missing. | Omitted from the SQL statement entirely. |
Sources: sea-orm-sync/src/entity/active_model.rs:23-45, sea-orm-sync/src/entity/active_model.rs:567-569
The ActiveModelTrait
The ActiveModelTrait defines the primary interface for CUD operations. It includes methods for setting values, checking changes, and executing database actions.
This diagram shows the relationship between core traits and lifecycle hooks.
Sources: sea-orm-sync/src/entity/active_model.rs:23-45, sea-orm-sync/src/entity/active_model.rs:629-645
Create Operations (Insert)
Insertion converts an ActiveModel into a new database record. By default, only fields marked as Set or Unchanged are included in the generated INSERT statement.
Insert Lifecycle
- before_save: The hook is executed with
insert: true. - Execution: The executor runs the
INSERTquery. - Returning: On databases like PostgreSQL, it uses the
RETURNINGclause; on MySQL/SQLite, it performs a subsequentSELECTusing the last insert ID. - after_save: The hook is executed with the resulting
Model.
Sources: sea-orm-sync/src/entity/active_model.rs:147-154, sea-orm-sync/src/entity/active_model.rs:633-645
Update Operations
Updates are "differential" by default. SeaORM examines the ActiveModel and only includes fields with the state ActiveValue::Set in the UPDATE statement's SET clause.
The Save Method
The save method is a convenience wrapper that performs an "Upsert-like" logic. It checks if the primary key is fully specified (indicating an existing record) to decide between insert and update.
This flowchart illustrates the internal logic of the save method.
Sources: sea-orm-sync/src/entity/active_model.rs:319-330, sea-orm-sync/src/entity/active_model.rs:333-343
Delete Operations
Deletion removes the record matching the ActiveModel primary key.
- Single Delete: Uses
ActiveModelTrait::delete. It requires the primary key to beSet. - Bulk Delete: Executed via
Entity::delete_many(), allowing filters to be applied before execution.
Sources: sea-orm-sync/src/entity/active_model.rs:372-381, sea-orm-sync/src/lib.rs:435-445
Nested Persistence (SeaORM 2.0)
SeaORM 2.0 introduced the ActiveModelEx (Extended) logic, usually triggered by the #[sea_orm::model] macro and builder(). This allows persisting entire object graphs (parent and children) in a single operation.
Lifecycle of Nested Operations
When an extended ActiveModel is saved, SeaORM automatically:
- Resolves Dependencies: Identifies which models must be inserted first (e.g., a Parent before a Child in a
BelongsTorelation). - Establishes Links: Automatically sets foreign keys on child models after the parent receives a database ID.
- Manages Junctions: For Many-to-Many relations, it handles the insertion and deletion of links in the junction table.
This sequence diagram shows how foreign keys are propagated during nested saves.
Sources: sea-orm-macros/src/derives/active_model_ex.rs:440-475, sea-orm-sync/examples/quickstart/src/main.rs:260-275
Implementation Details: establish_links
For M-N relations, the system uses establish_links to sync associations.
- delete_leftover: If enabled, associations in the junction table not present in the current
ActiveModelcollection are deleted. - on_conflict_do_nothing: Uses idempotent insertion for new junction rows to prevent errors on existing links.
Sources: sea-orm-sync/src/entity/active_model.rs:1052-1114, sea-orm-macros/src/derives/active_model_ex.rs:555-585
Conclusion
ActiveModel operations provide a type-safe, lifecycle-aware approach to database modifications. By utilizing stateful field tracking and automated relation handling in 2.0, SeaORM simplifies complex CUD tasks while maintaining optimal SQL performance.