使用Diesel的get_result出现trait bound错误,求问题排查
Actix + Diesel 插入数据后无法返回结果问题
问题场景
基于Actix框架开发API并结合Diesel ORM,在实现/books/create端点时,插入数据后无法将结果返回至代码中。
插入代码
use diesel::prelude::*; use crate::models::Book; use crate::schema::books; use crate::db; pub fn create_book(book: &Book) -> Book { let mut connection: SqliteConnection = db::establish_connection(); let result: QueryResult<Book> = diesel::insert_into(books::table) .values([book]) .get_result::<Book>(&mut connection); result.unwrap() }
错误说明
调用get_result时触发报错,核心矛盾在于SQLite的语法支持限制,同时Model设计存在逻辑冲突。
Model与Schema代码
Model定义
use diesel::prelude::*; use serde::{Serialize, Deserialize}; use crate::schema::books; #[derive(Queryable, Serialize, Deserialize, Insertable)] #[diesel(table_name = books)] pub struct Book { pub id: i32, pub title: String, pub author: String, pub creation_date: Option<String>, pub publishing_house: Option<String>, pub release_date: Option<String>, pub cover_image: Option<String> }
Schema定义
diesel::table! { books (id) { id -> Integer, title -> Text, author -> Text, publishing_house -> Nullable<Text>, release_date -> Nullable<Text>, cover_image -> Nullable<Text>, creation_date -> Nullable<Text>, } }
问题分析与解决方法
错误原因
- SQLite默认不支持RETURNING子句:Diesel的
get_result方法依赖数据库的RETURNING语法返回插入后的完整记录,但SQLite 3.35.0版本才引入该特性,旧版本直接报错。 - Insertable结构体包含自增ID:
Book中的id是数据库自增主键,插入时传入该字段不符合自增逻辑,且会导致无法正确获取数据库生成的ID。
解决步骤
方案一:拆分Insertable结构体(推荐,兼容所有SQLite版本)
创建专门用于插入的NewBook结构体,不包含自增id字段,插入后通过last_insert_rowid获取ID再查询完整记录:
// models.rs #[derive(Insertable)] #[diesel(table_name = books)] pub struct NewBook { pub title: String, pub author: String, pub creation_date: Option<String>, pub publishing_house: Option<String>, pub release_date: Option<String>, pub cover_image: Option<String> } // 插入函数修改为 pub fn create_book(new_book: &NewBook) -> Book { let mut connection = db::establish_connection(); diesel::insert_into(books::table) .values(new_book) .execute(&mut connection) .unwrap(); let last_id = connection.last_insert_rowid() as i32; books::table.find(last_id).get_result(&mut connection).unwrap() }
方案二:启用SQLite RETURNING支持(需SQLite ≥3.35.0)
- 在
Cargo.toml中添加Diesel的对应特性:
diesel = { version = "2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }
- 修改
Book结构体的Insertable属性,跳过id字段(插入时由数据库自动生成):
#[derive(Queryable, Serialize, Deserialize, Insertable)] #[diesel(table_name = books)] pub struct Book { #[diesel(skip)] pub id: i32, pub title: String, pub author: String, pub creation_date: Option<String>, pub publishing_house: Option<String>, pub release_date: Option<String>, pub cover_image: Option<String> }
- 此时可继续使用
get_result方法获取插入后的完整记录。
内容的提问来源于stack exchange,提问作者Zerok
相关产品推荐
相关产品推荐

