Rust Diesel实现通用更新函数时Identifiable trait绑定报错问题
问题根因
你使用的Diesel 1.4.x版本中,派生Identifiable trait时默认仅会为该类型的不可变引用实现trait,不会直接对类型本身生成实现。而你现有函数约束中要求Model: IntoUpdateTarget,该 trait 针对模型实例的实现依赖Model自身实现Identifiable,因此触发了编译报错。
解决方案
方案一:修改通用函数参数为引用(推荐)
调整函数参数和约束,直接接收旧模型的引用,匹配Diesel默认的Identifiable实现范围,同时还能避免不必要的对象克隆:
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> + HasTable + Identifiable, // 声明任意生命周期的Model引用都满足IntoUpdateTarget约束 for<'a> &'a Model: IntoUpdateTarget<Table = <Model as HasTable>::Table>, // 声明对应Update语句可以执行查询返回Model for<'a> Update<&'a Model, Model>: LoadQuery<PgConnection, Model> { updated_model.update_fields(user_id); // 去掉多余的unwrap,直接返回查询结果 diesel::update(old_model) .set(updated_model) .get_result(conn) }
调用时直接传入旧模型的引用即可,不需要再克隆:
common::dao::update(&conn2, &real_marking1[0], marking2_to_update, jwt_token.user_id)
方案二:手动为模型实现自身的Identifiable
如果确实需要传递旧模型的所有权,可手动为Marking等所有模型补充自身的Identifiable实现:
impl Identifiable for Marking { type Id = Uuid; fn id(&self) -> Self::Id { self.uuid } }
额外优化建议
你当前MetaFields实现中的self.ver.unwrap()存在panic风险,若数据库中某条记录的ver字段为NULL会直接崩溃,建议调整为带默认值的写法:
self.ver = Option::from(self.ver.unwrap_or(0) + 1);
内容的提问来源于stack exchange,提问作者Dmitrii
相关产品推荐
相关产品推荐

