8

我无法使用 Rocket 和 Diesel 从填充的 mySQL 数据库中检索日期时间。

这是我的模型:

extern crate chrono;

use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use schema::chrisms;
use diesel::sql_types::Datetime;
use self::chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};

#[derive(Serialize, Deserialize, Queryable)]
pub struct Chrisms {
    pub entity_ekklesia_location_id: i32,
    pub serie_number: Option<String>,
    pub seat_number: Option<String>,
    pub date: Datetime,
    pub year: i32,
    pub deleted: bool,
    pub entity_chrism_location_id: Option<i32>,
    pub entity_chrism_location_description: Option<String>,
    pub entity_rel_mec_id: Option<i32>,
    pub entity_rel_mec_description: Option<String>,
    pub created_by_user_id: Option<i32>,
    pub updated_by_user_id: Option<i32>,
    pub deleted_by_user_id: Option<i32>,
    pub created_at: Datetime,
    pub updated_at: Datetime,
    pub id: i32,
}

impl Chrisms {
    pub fn read(connection: &MysqlConnection) -> Vec<Chrisms> {
        chrisms::table.load::<Chrisms>(connection).unwrap()
    }
}

我的架构:

table! {
    chrisms (id) {
        entity_ekklesia_location_id -> Integer,
        serie_number -> Nullable<Varchar>,
        seat_number -> Nullable<Varchar>,
        date -> Datetime,
        year -> Integer,
        deleted -> Bool,
        entity_chrism_location_id -> Nullable<Integer>,
        entity_chrism_location_description -> Nullable<Varchar>,
        entity_rel_mec_id -> Nullable<Integer>,
        entity_rel_mec_description -> Nullable<Varchar>,
        created_by_user_id -> Nullable<Integer>,
        updated_by_user_id -> Nullable<Integer>,
        deleted_by_user_id -> Nullable<Integer>,
        created_at -> Datetime,
        updated_at -> Datetime,
        id -> Integer,
    }
}

这会产生错误:

1. the trait `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::Serialize` is not 
implemented for `diesel::sql_types::Datetime`
-required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::ser::SerializeStruct::serialize_field`

2. the trait `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::Deserialize<'_>` is 
not implemented for `diesel::sql_types::Datetime`
- required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::de::SeqAccess::next_element`
- required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::de::MapAccess::next_value`

3. the trait `diesel::Queryable<diesel::sql_types::Datetime, 
diesel::mysql::Mysql>` is not implemented for `diesel::sql_types::Datetime`
- required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, models::chrisms::Chrisms>` for `schema::chrisms::table`

我该如何解决?我测试了一堆用途,比如diesel:mysql_typesrocket:config等等,似乎不是问题所在。

4

1 回答 1

7

柴油创建/读取/更新/删除日期时间示例

货物.toml:

[dependencies]
diesel = { version = "1.4", features = ["sqlite", "chrono"] }
chrono = "0.4"

用户架构:

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    email TEXT NOT NULL UNIQUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
mod schema {
    table! {
        users (id) {
            id -> Integer,
            email -> Text,
            created_at -> Timestamp,
        }
    }
}
mod models {
    use super::schema::users;
    #[derive(Queryable, Debug)]
    pub struct User {
        pub id: i32,
        pub email: String,
        /// deisel create must enable chrono feature
        /// Timestamp without timezone, the memory align of Timestamp type in sqlite is same as libc::timeval?
        pub created_at: chrono::NaiveDateTime,
    }

    #[derive(Insertable)]
    #[table_name = "users"]
    pub struct UserInsert {
        pub email: String,
    }
}
#[macro_use]
extern crate diesel;
use diesel::{
    result::Error as DieselError, sql_types::BigInt, sqlite::SqliteConnection, Connection,
    ExpressionMethods, QueryDsl, RunQueryDsl,
};
use models::{User, UserInsert};
use schema::users::dsl::{created_at, id, users};

fn create_user(conn: &SqliteConnection, new_user_form: UserInsert) -> Result<User, DieselError> {
    // use sqlite(last_insert_rowid)/mysql(last_insert_id) to get current connection's last_insert_id
    // use .order(id.desc()).last() will get the wrong id when multi db_connections insert at same time
    no_arg_sql_function!(last_insert_rowid, BigInt);
    diesel::insert_into(users)
        .values(&new_user_form)
        .execute(conn)?;
    let new_user_id: i64 = diesel::select(last_insert_rowid).first(conn)?;
    let last_insert_user: User = users.filter(id.eq(new_user_id as i32)).first(conn)?;
    Ok(last_insert_user)
}

fn read_users(conn: &SqliteConnection) -> Result<Vec<User>, DieselError> {
    Ok(users.load::<User>(conn)?)
}

fn update_user_created_at(conn: &SqliteConnection, user_id: i32) -> Result<(), DieselError> {
    diesel::update(users.filter(id.eq(user_id)))
        .set(created_at.eq(chrono::Utc::now().naive_utc()))
        .execute(conn)?;
    Ok(())
}

fn delete_user_by_user_id(conn: &SqliteConnection, user_id: i32) -> Result<(), DieselError> {
    diesel::delete(users.filter(id.eq(user_id))).execute(conn)?;
    Ok(())
}

/// diesel CRUD(Create, Read, Update, Delete) example with datetime
fn main() -> Result<(), DieselError> {
    // TODO use r2d2 db_pool to enhance diesel performance
    let conn = SqliteConnection::establish("file:db.sqlite").unwrap();
    // clear all data before test
    diesel::delete(users).execute(&conn)?;
    let test_user_email = format!(
        "test+{}@example.com",
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs()
    );
    // CRUD - Create
    println!("\nCRUD - Create");
    let last_insert_user = create_user(
        &conn,
        UserInsert {
            email: test_user_email,
        },
    )?;
    dbg!(&last_insert_user);
    // CRUD - Read
    println!("\nCRUD - Read");
    dbg!(read_users(&conn)?);
    assert_eq!(read_users(&conn)?[0].id, last_insert_user.id);
    // CRUD - Update
    println!("\nCRUD - Update");
    update_user_created_at(&conn, last_insert_user.id)?;
    dbg!(read_users(&conn)?);
    assert_ne!(read_users(&conn)?[0].created_at, last_insert_user.created_at);
    // CRUD - Delete
    println!("\nCRUD - Delete");
    delete_user_by_user_id(&conn, last_insert_user.id)?;
    dbg!(read_users(&conn)?);
    assert!(read_users(&conn)?.is_empty());
    Ok(())
}

输出示例:

CRUD - Create
[src/main.rs:85] &last_insert_user = User {
    id: 1,
    email: "test+1606720099@example.com",
    created_at: 2020-11-30T07:08:19,
}

CRUD - Read
[src/main.rs:88] read_users(&conn)? = [
    User {
        id: 1,
        email: "test+1606720099@example.com",
        created_at: 2020-11-30T07:08:19,
    },
]

CRUD - Update
[src/main.rs:93] read_users(&conn)? = [
    User {
        id: 1,
        email: "test+1606720099@example.com",
        created_at: 2020-11-30T07:08:19.386513,
    },
]

CRUD - Delete
[src/main.rs:98] read_users(&conn)? = []
于 2020-04-13T04:01:35.773 回答