Rust中sqlx使用(另加若干报错解决办法)

1. Cargo.toml配置文件❗ ❗

[package]
name = "rust-sqlx"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
sqlx = { version = "0.7", features = [ "runtime-async-std", "tls-native-tls", "mysql", "macros", "chrono" ] }
async-std = {version = "1.12.0", features = ["attributes"]}
chrono = "0.4.38"

\quad\quad cargo.toml配置文件可参考crates.io进行配置,但有几点值得注意❗ ❗ ❗:

  • 如果选择runtime-async-std异步运行时,则需要开启它的attributesfeatures。否则在源文件中,入口函数处的#[async_std::main]会报错。
  • sqlxfeatures中需要添加mysql。否则use sqlx::mysql::MySqlPoolOptions;会报错。
  • sqlxfeatures中需要添加chrono。 否则无法完成数据库中datetime类型到chrono::NaiveDateTime类型的转换。
  • sqlxfeatures中需要添加macros。否则query!()以及query_as!()等宏会报错。
  • 由于是简单的入门程序,dotenvy以及序列化等crates暂时未引入。

2. 数据库中表结构

dept数据表

\quad\quad 在这里我的表结构如上所示。这个比较自由,根据自身实际情况选择即可。

3. 简单测试

\quad\quad 源文件主要修改自crates.io-sqlx中的示例程序。

❗❗❗ 注意,由于每个人的数据库密码,数据库名称,数据表的内容不尽相同,下面代码只具有参考意义,具体部分需要修改。

// use sqlx::postgres::PgPoolOptions;
use sqlx::mysql::MySqlPoolOptions;
use sqlx::Row;
use chrono::NaiveDateTime;
// etc.

/**
*	根据注释信息,我们提前在toml文件中设置以下内容,开启对应的feature
*	async-std = {version = "1.12.0", features = ["attributes"]}
*/
#[async_std::main] // Requires the `attributes` feature of `async-std`
// or #[tokio::main]
// or #[actix_web::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = MySqlPoolOptions::new()
                .max_connections(5)
                .connect("mysql://username:password@localhost/data_base_name").await?;

	// `table_name`为你自己的表名称
    let rows = sqlx::query("select * from table_name").fetch_all(&pool).await?;

    // 如果想要使用`get`函数通过索引列名访问数据,需要提前引入`sqlx::Row`
    /**
	*	get::<T, U>("column_name")
	*		其中`T`对应于`rust`程序中的类型
	*		其中`U`对应于查询类型,这里我们采用的是列名而不是索引,因此是`&str`
	*/
    for row in rows.iter() {
        println!("id {}, name {}, create_time {}", 
                row.get::<u32, &str>("id"), 
                row.get::<String, &str>("name"),
                row.get::<NaiveDateTime, &str>("create_time")
            );
    }

    Ok(())
}

\quad\quad 执行cargo run --release之后,在控制台便会输出

    Finished release [optimized] target(s) in 0.19s
     Running `target\release\rust-sqlx.exe`
id 1, name 学工部, create_time 2024-03-26 21:53:41
id 2, name 教研部, create_time 2024-03-26 21:53:41
id 3, name 咨询部, create_time 2024-03-26 21:53:41
id 4, name 就业部, create_time 2024-03-26 21:53:41
id 5, name 人事部, create_time 2024-03-26 21:53:41

4. FromRow完成自动映射

\quad\quad 上述代码需要手动的将数据库查询结果取出,并转换为对应的rust语言中的程序类型。显然是不符合实际情况的,需要想办法解决。

4.1 自定义结构体

\quad\quad 我们可以自定义一个结构体,让它代表数据表中记录数据的类型。

use chrono::NaiveDateTime;
use sqlx::FromRow;

#[derive(Debug, FromRow)]
pub struct Dept {
    id: u32,
    name: String,
    create_time: NaiveDateTime,
    update_time: NaiveDateTime,
}

\quad\quad 其中 FromRow这个trait完成了从表中的一条记录到程序中一个对象实例的转变。

4.2 代码分层

src
├─ dataobj
│ ├─ dept.rs
│ └─ mod.rs
└─ main.rs

\quad\quad 将代码划分成如上的属性结构。下面给出各部分的代码:

  1. dataobj/dept.rs部分
use chrono::NaiveDateTime;
use sqlx::FromRow;

#[derive(Debug, FromRow)]
pub struct Dept {
   id: u32,
   name: String,
   create_time: NaiveDateTime,
   update_time: NaiveDateTime,
}
  1. dataobj/mod.rs部分
pub mod dept;

  1. main.rs部分
use sqlx::mysql::MySqlPoolOptions;
use sqlx::Row;
use chrono::NaiveDateTime;

mod dataobj;
use dataobj::dept::Dept;

#[async_std::main] // Requires the `attributes` feature of `async-std`
async fn main() -> Result<(), sqlx::Error> {
    let pool = MySqlPoolOptions::new()
                .max_connections(5)
                .connect("mysql://username:password@host/database_name").await?;


	// `table_name`为你自己的表名称
    let rows = sqlx::query("select * from table_name").fetch_all(&pool).await?;

    println!("使用`query()`, 需要手动转换结果");
    // 如果想要使用`get`函数通过索引列名访问数据,需要提前引入`sqlx::Row`
    for row in rows.iter() {
        println!("id {}, name {}, create_time {}", 
                row.get::<u32, &str>("id"), 
                row.get::<String, &str>("name"),
                row.get::<NaiveDateTime, &str>("create_time")
            );
    }


    println!();
    let depts: Vec<Dept> = sqlx::query_as("select * from table_name").fetch_all(&pool).await?;
    
    println!("使用`query_as()`, 将查询结果转为自定义结构体");
    for dept in depts.iter() {
        println!("{:#?}", dept);
    }


    println!();
    let single_dept: Dept = sqlx::query_as("select * from table_name where id = ?")
            .bind(1)
            .fetch_one(&pool)
            .await?;
    println!("表中id为1的元素是: \n{:#?}", single_dept);

    Ok(())
}

\quad\quad 输出结果如下

使用`query()`, 需要手动转换结果
id 1, name 学工部, create_time 2024-03-26 21:53:41
id 2, name 教研部, create_time 2024-03-26 21:53:41
id 3, name 咨询部, create_time 2024-03-26 21:53:41
id 4, name 就业部, create_time 2024-03-26 21:53:41
id 5, name 人事部, create_time 2024-03-26 21:53:41

使用`query_as()`, 将查询结果转为自定义结构体
Dept {
    id: 1,
    name: "学工部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}
Dept {
    id: 2,
    name: "教研部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}
Dept {
    id: 3,
    name: "咨询部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}
Dept {
    id: 4,
    name: "就业部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}
Dept {
    id: 5,
    name: "人事部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}

表中id为1的元素是: 
Dept {
    id: 1,
    name: "学工部",
    create_time: 2024-03-26T21:53:41,
    update_time: 2024-03-26T21:53:41,
}
首先,你需要在你的 Rust 项目添加 sqlx 和 sqlx-core 依赖,可以在 Cargo.toml 文件添加如下内容: ```toml [dependencies] sqlx = "0.5" sqlx-core = "0.5" ``` 接下来,你需要定义一个数据模型来表示数据库的表。例如,考虑一个简单的用户表,包含 id、name 和 email 字段,你可以创建一个名为 User 的结构体来表示它: ```rust use sqlx::{FromRow, PgPool}; #[derive(Debug, FromRow)] struct User { id: i32, name: String, email: String, } ``` 接着,你需要创建一个 PostgreSQL 连接池,以便从数据库查询数据。你可以使用 `PgPool::connect` 方法来创建连接池: ```rust #[tokio::main] async fn main() -> Result<(), sqlx::Error> { let pool = PgPool::connect("postgres://user:password@host/database").await?; // ... Ok(()) } ``` 现在,你可以使用 sqlx 的查询宏来查询用户表的数据。例如,要查询所有用户的名称和电子邮件,可以使用如下代码: ```rust let users = sqlx::query_as::<_, User>("SELECT id, name, email FROM users") .fetch_all(&pool) .await?; ``` 这将返回一个包含所有用户的名称和电子邮件的 vector。如果你只想查询特定用户的数据,可以使用参数化查询: ```rust let user = sqlx::query_as::<_, User>("SELECT id, name, email FROM users WHERE id = $1") .bind(1) .fetch_one(&pool) .await?; ``` 这将返回 ID 为 1 的用户的名称和电子邮件。 当然,这只是一个简单的示例。使用 sqlx 还有很多更复杂的查询和操作,你可以参考 sqlx 的文档来学习更多内容。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值