Rust Diesel Abstract 更新函数
Posted
技术标签:
【中文标题】Rust Diesel Abstract 更新函数【英文标题】:Rust Diesel Abstract update function 【发布时间】:2021-12-24 13:45:58 【问题描述】:我目前正在尝试实现抽象函数,该函数将为数据库中的任何表更新一些元字段,但遇到了 Identifiable 问题。
我有一个数据库,其中每个表都有元字段:
....
pub updu: Option<Uuid>, // ID of a user who changed it
pub updt: Option<NaiveDateTime>, //updated with current date/time on every change
pub ver: Option<i32>, //Version increases on every change
.....
我想实现一个对每个实体进行更新的函数。目前我有这个实现:
pub fn update<Model>(
conn: &PgConnection,
old_model: Model,
mut updated_model: Model,
user_id: Uuid,
) -> Result<Model, diesel::result::Error>
where
Model: MetaFields + AsChangeset<Target = <Model as HasTable>::Table> + IntoUpdateTarget,
Update<Model, Model>: LoadQuery<PgConnection, Model>
updated_model.update_fields(user_id);
Ok(
diesel::update(old_model)
.set(updated_model)
.get_result(conn).unwrap()
)
当我尝试调用它时,它会显示此错误:
error[E0277]: the trait bound `Marking: Identifiable` is not satisfied
--> src/service/marking_service.rs:116:24
|
116 | web::block(move || common::dao::update(&conn2, real_marking1[0].clone(), marking2_to_update, jwt_token.user_id))
| ^^^^^^^^^^^^^^^^^^^ the trait `Identifiable` is not implemented for `Marking`
|
= help: the following implementations were found:
<&'ident Marking as Identifiable>
= note: required because of the requirements on the impl of `IntoUpdateTarget` for `Marking`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `testapi` due to previous error
我在本例中尝试更新的实体是:
use chrono::NaiveDateTime, Utc;
use common::model::MetaFields;
use common::utils::constants::DEL_MARK_AVAILABLE;
use serde::Deserialize, Serialize;
use serde_json;
use uuid::Uuid;
use crate::schema::marking;
#[derive(
Clone,
Serialize,
Deserialize,
Debug,
Queryable,
Insertable,
AsChangeset,
Identifiable,
QueryableByName,
Default,
)]
#[primary_key(uuid)]
#[table_name = "marking"]
pub struct Marking
pub uuid: Uuid,
pub updt: Option<NaiveDateTime>,
pub ver: Option<i32>,
pub updu: Option<Uuid>,
pub comment: Option<String>,
pub status: Option<String>,
impl MetaFields for Marking
fn update_fields(&mut self, user_id: Uuid)
self.updu = Option::from(user_id);
self.ver = Option::from(self.ver.unwrap() + 1);
self.updt = Option::from(Utc::now().naive_local());
如您所见,为该实体定义了 Identifiable,但由于某种原因更新无法看到它。有人可以建议我在这里缺少什么吗? 更新,架构:
table!
marking (uuid)
uuid -> Uuid,
updt -> Nullable<Timestamp>,
ver -> Nullable<Int4>,
updu -> Nullable<Uuid>,
comment -> Nullable<Varchar>,
status -> Nullable<Varchar>,
diesel = version = "1.4.6", features = ["postgres", "uuid", "chrono", "uuidv07", "serde_json"]
r2d2 = "0.8"
r2d2-diesel = "1.0.0"
diesel_json = "0.1.0"
【问题讨论】:
【参考方案1】:您的代码几乎是正确的。错误消息已经提到了这个问题:
#[derive(Identifiable)]
确实生成了以下 impl:impl<'a> Identifiable for &'a struct
,这意味着 trait 仅用于对 self 的引用。根据您的其他特征设置,您可以尝试以下操作:
old_model
common::dao::update
更改common::dao::update
的定义以将引用作为第二个参数。然后,您可以将 Model
的特征边界分开,以便将 IntoUpdateTarget
绑定在 &Model
上。
(很难猜测哪个会是更好的解决方案,因为您的问题缺少很多重要的上下文。请尝试在未来提供一个完整的最小示例。)
【讨论】:
感谢您的回复!这几乎是完整的示例,我添加了一些我认为没有必要的细节。我希望这就足够了。如果还有其他有用的信息,请提出建议。 @Dmitrii 我不确定在这里还能说什么。这与您的问题中缺少信息无关,而只是#[derive(Identifiable)]
生成了impl<'a> Identifable for &'a YourType
,这意味着它不是针对类型本身实现的,而仅针对类型的引用。这意味着您的代码可能永远不会以这种方式工作,至少在不更改更新函数的情况下不会。以上是关于Rust Diesel Abstract 更新函数的主要内容,如果未能解决你的问题,请参考以下文章
返回使用 Rocket 和 Diesel (Rust) 在 PostgreSQL 中创建的单个记录
使用 r2d2 在 rust/diesel 应用程序中实现连接池
Rust Diesel 原始 SQL 给出错误“`std::result::Result<Vec<T>,diesel::result::Error>` 所需的类型注释”