首页 文章

使用trait作为数据库实体的接口

提问于
浏览
1

我正在尝试创建一个 Entity 接口,用于将数据库结果动态映射到Rust结构中:

pub trait Entity {
    fn map(&self, Result<QueryResult>) -> Self;
}

pub struct DbQuery<T> {
    pub sql: String,
    pub params: Vec<Value>,
    pub limit: i32,
    pub paged: Option<Pagination>,
    pub entity: T,
}

pub struct Settings {
    pub name: String,
    pub value: Option<String>,
}

impl Entity for Settings {
    fn map(&self, result: Result<QueryResult>) -> Settings {
        // ...
        Settings {
            name: "hello".to_string(),
            value: None,
        }
    }
}

impl DbMapper {
    // ...

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
        println!("query find SQL: {}", query.sql);
        let mut stmt = &self.pool.prepare(query.sql).unwrap();
        let ret = Vec::new();
        for row in stmt.execute(query.params).unwrap() {
            ret.push(query.entity.map(row.unwrap()));

        }

        Some(ret)
    }
}

但是我收到一个错误:

错误:当前作用域中没有为类型T找到名为map的方法ret.push(query.entity.map(row.unwrap())); |注意:方法映射存在,但不满足以下特征边界:T:std :: iter :: Iterator = help:特征中的项目只能在特征实现且在范围内时使用;以下特征定义了一个项目图,也许你需要实现其中一个:= help:candidate#1:models :: holder :: database :: Entity = help:candidate#2:std :: iter :: Iterator

1 回答

  • 3

    Here is a version of your code that runs on the playground并复制您的问题:

    pub struct QueryResult;
    pub struct Value;
    pub struct Pagination;
    pub struct DbMapper;
    
    pub trait Entity {
        fn map(&self, Result<QueryResult, ()>) -> Self;
    }
    
    pub struct DbQuery<T> {
        pub sql: String,
        pub params: Vec<Value>,
        pub limit: i32,
        pub paged: Option<Pagination>,
        pub entity: T,
    }
    
    pub struct Settings {
        pub name: String,
        pub value: Option<String>,
    }
    
    impl Entity for Settings {
        fn map(&self, result: Result<QueryResult, ()>) -> Settings {
            // ...
            Settings {
                name: "hello".to_string(),
                value: None,
            }
        }
    }
    
    impl DbMapper {
        // ...
    
        pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
            println!("query find SQL: {}", query.sql);
    
            // ########## attempt to call map()
            let _ = query.entity.map(Ok(QueryResult {}));
    
            let ret = Vec::new();
            Some(ret)
    
        }
    }
    
    fn main() {}
    

    问题是 find 方法中的 DbQuery<T> 参数中的 T 不知道 TEntity 类型 . 所以我们需要告诉它:

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>>
        where T: Entity
    {
        // ... code here ...
    }
    

    This now compiles and runs .

    编译器现在知道 T 是某些描述的 Entity ,并且可以在其上调用 map 方法 .

相关问题