Expanded Entity Structure
SeaORM is dynamic, which means you have the flexibility to configure things on runtime. If you are curious what the DeriveEntityModel expands into, read along. Otherwise, you can skip this for now.
The expanded entity format can be generated by sea-orm-cli with the --expanded-format option.
Let's go through the sections of the expanded Cake entity.
Entityβ
By implementing the EntityTrait, you can perform CRUD operations on the given table.
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;
impl EntityName for Entity {
fn schema_name(&self) -> Option<&str> {
None
}
fn table_name(&self) -> &str {
"cake"
}
}
Columnβ
An enum representing all columns in this table.
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
Id,
Name,
}
impl ColumnTrait for Column {
type EntityName = Entity;
fn def(&self) -> ColumnDef {
match self {
Self::Id => ColumnType::Integer.def(),
Self::Name => ColumnType::String(None).def(),
}
}
}
All column names are assumed to be in snake-case.
pub enum Column {
Id, // maps to "id" in SQL
Name, // maps to "name" in SQL
CreateAt // maps to "create_at" in SQL
}
To specify the datatype of each column, the ColumnType enum can be used.
Additional propertiesβ
- Unique
- Indexed
- Nullable
ColumnType::String(None).def().unique().indexed().nullable()
Primary Keyβ
An enum representing the primary key of this table. If it is a composite key, then multiple enum variants can be added.
The ValueType define the return type of last insert id in InsertResult.
The auto_increment defines whether the primary key has an auto-generated value.
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
Id,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = i32;
fn auto_increment() -> bool {
true
}
}
Example composite key
pub enum PrimaryKey {
CakeId,
FruitId,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = (i32, i32);
fn auto_increment() -> bool {
false
}
}
Modelβ
The Rust struct for storing the query results.
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
pub struct Model {
pub id: i32,
pub name: String,
}
Nullable Attributeβ
If the table column is nullable, wrap it with an Option.
pub struct Model {
pub id: i32,
pub name: Option<String>,
}
Active Modelβ
The ActiveModel has all the attributes of its corresponding Model but all attributes are wrapped in an ActiveValue.
#[derive(Clone, Debug, PartialEq)]
pub struct ActiveModel {
pub id: ActiveValue<i32>,
pub name: ActiveValue<Option<String>>,
}
Active Model Behaviorβ
Handlers for different triggered actions on an ActiveModel. For example, you can perform custom validation logic, preventing a model from saving into database. You can abort an action even after it is done, if you are inside a transaction.
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
fn before_save(self, insert: bool) -> Result<Self, DbErr> {
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
fn after_save(self, insert: bool) -> Result<Self, DbErr> {
Ok(self)
}
/// Will be triggered before delete
fn before_delete(self) -> Result<Self, DbErr> {
Ok(self)
}
/// Will be triggered after delete
fn after_delete(self) -> Result<Self, DbErr> {
Ok(self)
}
}
If no customization is needed, simply write:
impl ActiveModelBehavior for ActiveModel {}
Relationβ
Specifying the relations with other entities.
#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
Fruit,
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
}
}
}
Relatedβ
Defining trait bounds to help you query related entities together, especially helpful in many-to-many relations.
impl Related<super::fruit::Entity> for Entity {
fn to() -> RelationDef {
Relation::Fruit.def()
}
}
impl Related<super::filling::Entity> for Entity {
fn to() -> RelationDef {
super::cake_filling::Relation::Filling.def()
}
fn via() -> Option<RelationDef> {
Some(super::cake_filling::Relation::Cake.def().rev())
}
}