Skip to content

Entity Loader with Diamond RelationsΒ #3021

@Huliiiiii

Description

@Huliiiiii

Discussed in #3020

Originally posted by thorsonlinguistics March 26, 2026
I'm trying to implement types that have a diamond relation. I've followed the documentation on diamond relations, but it doesn't seem to work as expected with the entity loader - the code compiles but the related fields are Unloaded on the ModelEx. A MWE is given below, following the quickstart example. The result is ModelEx { id: 1, name: "YumBakery", manager_id: 1, cashier_id: 2, manager: Unloaded, cashier: Unloaded }, but I'm expected manager and cashier to be loaded with the manager and cashier. Is there a different way I should be defining the attributes, or a different way I should be calling .with()?

use log::info;

mod bakery {
    use sea_orm::entity::prelude::*;

    #[sea_orm::model]
    #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
    #[sea_orm(table_name = "bakery")]
    pub struct Model {
        #[sea_orm(primary_key)]
        pub id: i32,
        pub name: String,
        pub manager_id: i32,
        pub cashier_id: i32,
        #[sea_orm(belongs_to, relation_enum = "Manager", from = "manager_id", to = "id")]
        pub manager: HasOne<super::worker::Entity>,
        #[sea_orm(belongs_to, relation_enum = "Cashier", from = "cashier_id", to = "id")]
        pub cashier: HasOne<super::worker::Entity>,
    }

    impl ActiveModelBehavior for ActiveModel {}
}

mod worker {
    use sea_orm::entity::prelude::*;

    #[sea_orm::model]
    #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
    #[sea_orm(table_name = "worker")]
    pub struct Model {
        #[sea_orm(primary_key)]
        pub id: i32,
        pub name: String,
        #[sea_orm(has_many, relation_enum = "BakeryManager", via_rel = "Manager")]
        pub manager_of: HasMany<super::bakery::Entity>,
        #[sea_orm(has_many, relation_enum = "BakeryCashier", via_rel = "Cashier")]
        pub cashier_of: HasMany<super::bakery::Entity>,
    }

    impl ActiveModelBehavior for ActiveModel {}
}

#[tokio::main]
async fn main() -> Result<(), sea_orm::DbErr> {
    ///// Part 0: Setup Environment /////

    // This disables sqlx's logging and enables sea-orm's logging with parameter injection,
    // which is easier to debug.
    let env = env_logger::Env::default().filter_or("RUST_LOG", "info,sea_orm=debug,sqlx=warn");
    env_logger::Builder::from_env(env).init();

    use sea_orm::{entity::*, query::*};

    // Use a SQLite in memory database so no setup needed.
    // SeaORM supports MySQL, Postgres, SQL Server as well.
    let db = &sea_orm::Database::connect("sqlite::memory:").await?;

    // Populate this fresh database with tables.
    //
    // All entities defined in this crate are automatically registered
    // into the schema registry, regardless of which module they live in.
    //
    // The registry may also include entities from upstream crates,
    // so here we restrict it to entities defined in this crate only.
    //
    // The order of entity definitions does not matter.
    // SeaORM resolves foreign key dependencies automatically
    // and creates the tables in the correct order with their keys.
    db.get_schema_registry("seatest::*")
        .sync(db)
        .await?;

    info!("Schema created.");

    ///// Part 1: CRUD with nested 1-1 and 1-N relations /////
    
    info!("Create worker Bob");
    let bob = worker::ActiveModel::builder()
        .set_name("Bob")
        .insert(db)
        .await?;

    info!("Create worker Alice");
    let alice = worker::ActiveModel::builder()
        .set_name("Alice")
        .insert(db)
        .await?;

    info!("Create bakery with workers Alice and Bob");
    let yum = bakery::ActiveModel::builder()
        .set_name("YumBakery")
        .set_manager_id(bob.id)
        .set_cashier_id(alice.id)
        .set_manager(worker::ActiveModel::builder().set_name("Bob"))
        .set_cashier(worker::ActiveModel::builder().set_name("Alice"))
        .insert(db)
        .await?;

    info!("Querying bakeries with workers");
    let yum = bakery::Entity::load()
        .filter_by_id(yum.id)
        .with(bakery::Relation::Manager)
        .with(bakery::Relation::Cashier)
        .one(db)
        .await?
        .unwrap();

    println!("{:?}", yum);

    Ok(())
}
```</div>

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions