changelog/2.0.0.md
SeaORM 2.0 is the first stable release of the 2.x line. It reworks how entities, relations, and ActiveModels are defined and used, adds an entity-first workflow, introduces role-based access control, and brings the library onto SeaQuery 1.0 and SQLx 0.9.
The full, itemized changelog for the 2.0 series (all release candidates included) is in CHANGELOG.md.
Relations are now declared directly on the Model struct with #[sea_orm::model],
replacing the separate Relation enum and Related impls.
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
}
See the new entity format walk-through.
BelongsTo relation type with compile-time cardinalityA belongs_to relation can be typed BelongsTo<Entity> (required) or
BelongsTo<Option<Entity>> (optional), encoding the foreign-key cardinality in the
type and paired with the write-side ActiveBelongsTo. The macro validates the type
against the nullability of the from columns at compile time. BelongsTo is the
recommended type for belongs_to; the legacy HasOne<Entity> field type remains
supported for backward compatibility. (https://github.com/SeaQL/sea-orm/pull/3118)
Filter with the typed COLUMN constant for compile-time type safety, alongside the
existing Column enum.
user::Entity::find().filter(user::COLUMN.name.contains("Bob"))
Build and persist an entity together with its related rows in one expression, and push has-many children onto a loaded model.
let bob = user::ActiveModel::builder()
.set_name("Bob")
.set_email("[email protected]")
.set_profile(profile::ActiveModel::builder().set_picture("Tennis"))
.insert(db)
.await?;
See nested ActiveModel.
Load an entity together with its relations, including nested relations, in a single call.
let user = user::Entity::load()
.filter_by_id(12)
.with(profile::Entity)
.with((post::Entity, comment::Entity))
.one(db)
.await?;
Create tables directly from entity definitions via the schema registry, without writing a migration first.
db.get_schema_registry("my_crate::*").sync(db).await?;
See the entity-first workflow.
A table-scoped, hierarchical RBAC engine with a query auditor and a
RestrictedConnection that implements ConnectionTrait and enforces permissions on
all Entity operations (including complex joins, insert-select, and CTE queries).
(https://github.com/SeaQL/sea-orm/pull/2683)
insert_manyinsert_many no longer shares a helper struct with single insert. Panic-prone APIs
were removed, empty input returns None / vec![] on exec, and the new InsertMany
helper exposes last_insert_id: Option<Value>. (https://github.com/SeaQL/sea-orm/pull/2628)
The sea-orm-sync crate provides a synchronous SeaORM backed by rusqlite, mirroring
the async API with async/await stripped away.
Follow the 1.0 to 2.0 migration guide and the 2.0 walk-through.
Notable breaking changes to be aware of:
.eq(), .like(), .contains() now require
use sea_orm::ExprTrait; in scope. Also read
SeaQuery's breaking changes.execute / query_one / query_all / stream now take a SeaQuery statement; the
raw-SQL variants are execute_raw / query_one_raw / query_all_raw / stream_raw.GENERATED BY DEFAULT AS IDENTITY instead
of serial; opt back in with option-postgres-use-serial if needed.Integer and BigInteger to integer.DeriveValueType now also derives NotU8, IntoActiveValue, and TryFromU64;
remove any manual implementations to avoid conflicts.runtime-actix feature alias (use runtime-tokio); removed
DeriveCustomColumn and default_as_str.