rust:axum+sqlx实战学习笔记4

您所在的位置:网站首页 rust无法连接 rust:axum+sqlx实战学习笔记4

rust:axum+sqlx实战学习笔记4

2023-12-19 22:21| 来源: 网络整理| 查看: 265

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

通过前面3个章节,我们对axum的基本使用已经大概掌握,能够进行简单上手了。一个后端服务,除了路由分发框架,自然需要操作数据库。在这里,我们选择sqlx访问数据库。 至于sqlx,以下是它的简介:

sqlx 是 rust 中的一个数据库访问工具。具有以下特点:

异步:原生就支持异步,在并发性高的场合能够得到更好的支持 编译时检查查询:sqlx可以在 cargo build 的时候检查执行sql和响应值 多数据库支持:PostgresSQL,MySql,SqlLite,MSSql,MariaDB 多运行时支持:支持主流 rust 运行时。async-std,tokio,actix,native-tls,rustls 内置连接池,支持查询缓存

但是,sqlx 并不是 orm 框架

接下来,我们进入sqlx的世界。

首先还是看官方文档:

use sqlx::postgres::PgPoolOptions; // use sqlx::mysql::MySqlPoolOptions; // etc. #[async_std::main] // or #[tokio::main] // or #[actix_web::main] async fn main() -> Result { // Create a connection pool // for MySQL, use MySqlPoolOptions::new() // for SQLite, use SqlitePoolOptions::new() // etc. let pool = PgPoolOptions::new() .max_connections(5) .connect("postgres://postgres:password@localhost/test").await?; // Make a simple query to return the given parameter (use a question mark `?` instead of `$1` for MySQL) let row: (i64,) = sqlx::query_as("SELECT $1") .bind(150_i64) .fetch_one(&pool).await?; assert_eq!(row.0, 150); Ok(()) }

这里只是简单得演示了sqlx如何连接数据库,这部分也没啥好说的,唯一要注意的是,连接不同的数据库,最好使用不同的连接池postgres引用PgPoolOptions,mysql使用MySqlPoolOptions。 当然,如果你想要一个通用的连接池,那可以使用 sqlx::​any::​AnyPoolOptions

接下来才是重点,sqlx中如何进行sql操作,大体上可以分成两类:

方法一:使用query!宏

// let mut conn = ; let account = sqlx::query!("select (1) as id, 'Herp Derpinson' as name") .fetch_one(&mut conn) .await?; // anonymous struct has `#[derive(Debug)]` for convenience println!("{:?}", account); println!("{}: {}", account.id, account.name);

也可以使用struct对返回的数据进行映射

#[derive(Debug)] struct Account { id: i32, name: String } // let mut conn = ; let account = sqlx::query_as!( Account, "select * from (select (1) as id, 'Herp Derpinson' as name) accounts where id = ?", 1i32 ) .fetch_one(&mut conn) .await?; println!("{:?}", account); println!("{}: {}", account.id, account.name);

方法二:使用query函数

pub async fn create_item(payload: CreateTodoItem) -> Result { let sql = "insert into todo_item(title, list_id) values (?, ?)"; let pool = db::get_pool().unwrap(); let affect_rows = sqlx::query(sql) .bind(payload.title) .bind(payload.list_id) .execute(pool) .await? .rows_affected(); Ok(affect_rows) }

同理,用struct对返回的数据进行映射用query_as函数,但是需要实现FromRow这个特质

/// 待办事项模型 #[derive(Debug, Clone, Deserialize, Serialize, FromRow)] pub struct TodoListItem { pub id: u32, pub title: String, pub checked: bool, pub list_id: u32, } pub async fn item_list(id: u32) -> Result { let pool = db::get_pool().unwrap(); let sql = "select id, title, checked, list_id from todo_item where list_id = ?"; let list = sqlx::query_as::(sql) .bind(id) .fetch_all(pool) .await?; Ok(list) }

当然,操作数据库的宏和函数不止这几个,不过常用的操作已经够了。

接下来是执行函数:

pub trait Executor>     where         'q: 'e,         'c: 'e,         E: 'q + Execute>     where         'q: 'e,         'c: 'e,         E: 'q + Execute>::Statement, Error>> + Send + 'e, Global>>     where         'q: 'e,         'c: 'e; fn execute(         self,         query: E     ) -> Pin>     where         'q: 'e,         'c: 'e,         E: 'q + Execute>     where         'q: 'e,         'c: 'e,         E: 'q + Execute>     where         'q: 'e,         'c: 'e,         E: 'q + Execute>     where         'q: 'e,         'c: 'e,         E: 'q + Execute Pin>     where         'q: 'e,         'c: 'e, { ... } }

可以看出主要有: fetch_many、fetch_optional、prepare_with、execute、execute_many、 fetch、fetch_all、 fetch_one、prepare 等方法。

更具体的说明可以看文档,我们通过上面的例子和函数名字,基本也能够了解这些函数的用处。

总结:今天的sqlx操作数据库其实非常简单,只有几个常用api,然后写入对应的sql语句即可。(你要我写详细点,臣妾也做不到啊,毕竟官方文档就给了几个例子)

踩坑点: sqlx当然没有这么容易就结束了,真正的麻烦现在才开始。

踩坑一:rust类型与sqlx类型问题

rust类型与sqlx读写数据库的类型之间如何要匹配,sqlx文档其实有介绍,不同的数据库需要找到对应的类型,不然用query_as进行类型映射就会报错。

1660198503416.png

这里以我用的数据库MySQL为例,常见的文字、数字类型都有明确的类型。

image.png

而时间类型需要用到第三方库chrono或者time。特别要注意的是,还需要在Cargo Feature中配置对应的设置,要不然无法匹配时间类型。(我曾因为时间类型而卡了好几天,最后才发现要配置Feature,而且sqlx的Feature在官方文档居然没有说明,而是在github上面,真是巨坑!)

1660199205837.png

当然,大佬们更多都是看源码的。更多内容的可以看官方源码。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3