Skip to main content
Version: 1.2.x 🚧

Entity Structure

Let's look at a simple Cake entity.

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cake")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::fruit::Entity")]
Fruit,
}

impl Related<super::fruit::Entity> for Entity {
fn to() -> RelationDef {
Relation::Fruit.def()
}
}

impl ActiveModelBehavior for ActiveModel {}
info

Do not delete the Relation enum or ActiveModelBehavior impl block even if they are empty.

Entity

The DeriveEntityModel macro does all the heavy lifting of defining an Entity with associating Model, Column and PrimaryKey.

Table Name

The table_name attribute specifies the corresponding table in the database. Optionally, you can also specify the database schema or database name by schema_name.

Column Names

By default, all column names are assumed to be in snake_case. You can override this behaviour for all columns in a model by specifying the rename_all attribute.

#[sea_orm(rename_all = "camelCase")]
pub struct Model { ... }
You can find a list of valid values for the `rename_all` attribute here
  • camelCase
  • kebab-case
  • mixed_case
  • SCREAMING_SNAKE_CASE
  • snake_case
  • title_case
  • UPPERCASE
  • lowercase
  • SCREAMING-KEBAB-CASE
  • PascalCase

Column

Column Name

You can override the column name by specifying the column_name attribute.

#[derive(DeriveEntityModel)]
#[sea_orm(table_name = "user", rename_all = "camelCase")]
pub struct Model {
#[sea_orm(primary_key)]
id: i32,
first_name: String, // firstName
#[sea_orm(column_name = "lAsTnAmE")]
last_name: String, // lAsTnAmE
}

Column Type

The column type will be derived automatically with the following mapping:

SQL Server (MSSQL) backend

The column type mapping of MSSQL can be found here.

For the mappings of Rust primitive data types.

Rust typeDatabase Type
(ColumnType)
SQLite
datatype
MySQL
datatype
PostgreSQL
datatype
StringCharcharcharchar
StringStringvarcharvarcharvarchar
i8TinyIntegertinyinttinyintchar
u8TinyUnsignedtinyinttinyint unsignedN/A
i16SmallIntegersmallintsmallintsmallint
u16SmallUnsignedsmallintsmallint unsignedN/A
i32Integerintegerintinteger
u32Unsignedintegerint unsignedN/A
i64BigIntegerbigintbigintbigint
u64BigUnsignedbigintbigint unsignedN/A
f32Floatfloatfloatreal
f64Doubledoubledoubledouble precision
boolBooleanbooleanboolbool
Vec<u8>Binaryblobblobbytea

For the mappings of Rust non-primitive data types. You can check entity/prelude.rs for all of the reexported types.

Rust typeDatabase Type
(ColumnType)
SQLite
datatype
MySQL
datatype
PostgreSQL
datatype
Date: chrono::NaiveDate
TimeDate: time::Date
Datedate_textdatedate
Time: chrono::NaiveTime
TimeTime: time::Time
Timetime_texttimetime
DateTime: chrono::NaiveDateTime
TimeDateTime: time::PrimitiveDateTime
DateTimedatetime_textdatetimetimestamp
DateTimeLocal: chrono::DateTime<Local>
DateTimeUtc: chrono::DateTime<Utc>
Timestamptimestamp_texttimestampN/A
DateTimeWithTimeZone: chrono::DateTime<FixedOffset>
TimeDateTimeWithTimeZone: time::OffsetDateTime
TimestampWithTimeZonetimestamp_with_timezone_texttimestamptimestamp with time zone
Uuid: uuid::Uuid, uuid::fmt::Braced, uuid::fmt::Hyphenated, uuid::fmt::Simple, uuid::fmt::UrnUuiduuid_textbinary(16)uuid
Json: serde_json::ValueJsonjson_textjsonjson
Decimal: rust_decimal::DecimalDecimalrealdecimaldecimal

You can override the default mappings between a Rust type and ColumnType by the column_type attribute.

#[sea_orm(column_type = "Text")]
pub name: String

If you need your JSON field to be deserialized into a struct. You would need to derive FromJsonQueryResult for it.

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "json_struct")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
// JSON column defined in `serde_json::Value`
pub json: Json,
// JSON column defined in custom struct
pub json_value: KeyValue,
pub json_value_opt: Option<KeyValue>,
}

// The custom struct must derive `FromJsonQueryResult`, `Serialize` and `Deserialize`
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
pub struct KeyValue {
pub id: i32,
pub name: String,
pub price: f32,
pub notes: Option<String>,
}
info

Array datatype is a Postgres-only feature. You can define a vector of types that are already supported by SeaORM.

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "collection")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub integers: Vec<i32>,
pub integers_opt: Option<Vec<i32>>,
pub floats: Vec<f32>,
pub doubles: Vec<f64>,
pub strings: Vec<String>,
}

Additional Properties

You can add additional properties default_value, unique, indexed and nullable to a column.

If you specified a custom column_type for an optional attribute, you must also specify nullable.

#[sea_orm(column_type = "Text", default_value = "Sam", unique, indexed, nullable)]
pub name: Option<String>

Cast Column Type on Select and Save

If you need to select a column as one type but save it into the database as another, you can specify the select_as and the save_as attributes to perform the casting. A typical use case is selecting a column of type citext (case-insensitive text) as String in Rust and saving it into the database as citext. One should define the model field as below:

#[sea_orm(select_as = "text", save_as = "citext")]
pub case_insensitive_text: String

Ignore Attribute

If you want to ignore a particular model attribute such that it maps to no database column, you can use the ignore annotation.

#[sea_orm(ignore)]
pub ignore_me: String

Primary Key

Use the primary_key attribute to mark a column as the primary key.

#[sea_orm(primary_key)]
pub id: i32

Auto Increment

By default, auto_increment is implied for primary_key column. Override it by specifying false.

#[sea_orm(primary_key, auto_increment = false)]
pub id: i32

Composite Key

This is usually the case in junction tables, where a two-column tuple is used as the primary key. Simply annotate multiple columns to define a composite primary key. auto_increment is false for composite key.

The max arity of a primary key is 12.

pub struct Model {
#[sea_orm(primary_key)]
pub cake_id: i32,
#[sea_orm(primary_key)]
pub fruit_id: i32,
}

Relation

DeriveRelation is a macro to help you implement the RelationTrait.

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::fruit::Entity")]
Fruit,
}

If there are no relations, simply write:

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

The Related trait connects entities together, such that you can build queries selecting both entities.

Learn more about relations in the Relation chapter.

Active Model Behavior

Hooks for different actions on an ActiveModel. For example, you can perform custom validation logic or trigger side effects. Inside a transaction, you can even abort an action after it is done, preventing it from saving into the database.

#[async_trait]
impl ActiveModelBehavior for ActiveModel {
/// Create a new ActiveModel with default values. Also used by `Default::default()`.
fn new() -> Self {
Self {
uuid: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}

/// Will be triggered before insert / update
async fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
if self.price.as_ref() <= &0.0 {
Err(DbErr::Custom(format!(
"[before_save] Invalid Price, insert: {}",
insert
)))
} else {
Ok(self)
}
}

/// Will be triggered after insert / update
async fn after_save<C>(model: Model, db: &C, insert: bool) -> Result<Model, DbErr>
where
C: ConnectionTrait,
{
Ok(model)
}

/// Will be triggered before delete
async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
Ok(self)
}

/// Will be triggered after delete
async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
Ok(self)
}
}

If no customization is needed, simply write:

impl ActiveModelBehavior for ActiveModel {}