#3183·sea-orm

嵌套 ActiveModelEx::save() 无法插入具有复合非自动增量主键的新 has_many 子对象

作者: ziimakc创建于 2026年8月22日更新于 2026年9月10日
rust
use sea_orm::entity::prelude::*;
use sea_orm::{ConnectionTrait, Database, Schema};

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

    #[sea_orm::model]
    #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
    #[sea_orm(table_name = "parent")]
    pub struct Model {
        #[sea_orm(primary_key, auto_increment = false)]
        pub id: i32,
        #[sea_orm(has_many)]
        pub children: HasMany<super::child::Entity>,
    }

    impl ActiveModelBehavior for ActiveModel {}
}

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

    // Composite, non-auto-increment primary key.
    #[sea_orm::model]
    #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
    #[sea_orm(table_name = "child")]
    pub struct Model {
        #[sea_orm(primary_key, auto_increment = false)]
        pub parent_id: i32,
        #[sea_orm(primary_key, auto_increment = false)]
        pub tag: i32,
        #[sea_orm(belongs_to, from = "parent_id", to = "id")]
        pub parent: HasOne<super::parent::Entity>,
    }

    impl ActiveModelBehavior for ActiveModel {}
}

#[tokio::main]
async fn main() -> Result<(), DbErr> {
    let db = Database::connect("sqlite::memory:").await?;
    let builder = db.get_database_backend();
    let schema = Schema::new(builder);
    db.execute(&schema.create_table_from_entity(parent::Entity)).await?;
    db.execute(&schema.create_table_from_entity(child::Entity)).await?;

    parent::ActiveModel::builder().set_id(1).insert(&db).await?;

    let loaded = parent::Entity::load()
        .filter(parent::COLUMN.id.eq(1))
        .one(&db)
        .await?
        .expect("parent exists");

    let mut active: parent::ActiveModelEx = loaded.into();
    active.children.push(child::ActiveModel::builder().set_tag(42));

    let result = active.save(&db).await; // <- fails
    println!("{:?}", result.map(|_| ()));

    Ok(())
}