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

时间:2016-11-22 10:57:47

标签: rust traits

我正在尝试创建一个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)
    }
}

但是我收到了一个错误:

  

错误:当前范围中没有为类型map找到名为T的方法   ret.push(query.entity.map(row.unwrap())); |
  注意:方法map存在,但具有以下特征   边界不满意:T : std::iter::Iterator =帮助:项目   只有在特征实施和范围内时才能使用特征;   以下特征定义了一个项map,也许你需要   实施其中之一:=帮助:候选人#1:   models::holders::database::Entity =帮助:候选人#2:   std::iter::Iterator

1 个答案:

答案 0 :(得分: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() {}

问题是T方法中DbQuery<T>参数中的find不知道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方法。