Rust - mysql 新的選擇

一、添加mysql依賴

sqlx 是同時支持tokio2.0和async-std的異步mysql

[dependencies]
tokio = {version = "0.2.15", features = ["full"] }
sqlx = {version = "0.3", default-features = false, features = ["runtime-tokio", "mysql", "chrono"]}

PS: 爲什麼不添加macro的feature,是因爲這些宏的使用,需要在編譯器連接到數據庫纔行

二、設置database_url,創建連接池

DSN:mysql://root:[email protected]:3306/testdb
支持的連接池的參數如下:

    pub max_size: u32, // 連接池的上限
    pub connect_timeout: Duration, // 連接超時時間
    pub min_size: u32, // 連接池的下限
    pub max_lifetime: Option<Duration>, // 所有連接的最大生命週期
    pub idle_timeout: Option<Duration>, // 空閒連接的生命週期

創建連接池:

    let pool = sqlx::MySqlPool::builder().
        max_size(100).
        min_size(10).
        connect_timeout(std::time::Duration::from_secs(10)).
        max_lifetime(std::time::Duration::from_secs(1800)).
        idle_timeout(std::time::Duration::from_secs(600)).
        build(&std::env::var("DATABASE_URL").unwrap()).await?;
三、查詢sql結果

1、使用fetch,獲取cursor遊標,自己處理row

    let sql = "select id, username from t_user where id < ?";
    let mut cursor = sqlx::query(sql).bind(3).fetch(&pool);
    while let Some(row) = cursor.next().await? {
        let user = User {
            id: row.get("id"),
            username: row.get("username"),
        };
        println!("{:?}", user);
    }

2、使用fetch,加map,自動處理row

	#[derive(Debug)]
	struct User {
   		id: u32,
    	username: String,
	}
	// -------------------
    let sql = "select id, username from t_user limit 10";
    let stream = sqlx::query(sql)
        .map(|row: sqlx::mysql::MySqlRow| User {
            id: row.try_get("id").unwrap_or(0),
            username: row.try_get("username").unwrap_or("".into()),
        })
        .fetch(&pool);

    tokio::pin!(stream);

    while let Some(user) = stream.try_next().await? {
        println!("{:?}", user);
    }

3、使用execute,執行更新操作,返回affect_rows

    let sql = r#"update t_user set username = ? where id > ?"#;
    let mut affect_rows = sqlx::query(sql).bind("wy").bind(1).execute(&pool).await?;
    println!("{:?}", affect_rows);

4、使用execute和fetch,執行插入操作,獲取自增id

    let mut conn = pool.acquire().await?;

    let sql = r#"insert into t_user (username, password) value (?, ?);"#;
    let affect_rows = sqlx::query(sql).bind("wy").bind("123456").execute(&mut conn).await?;
    println!("{:?}", affect_rows);

    let sql = r#"select last_insert_id();"#;
    // use tokio::stream::StreamExt;
    let insert_id: u64 = sqlx::query(sql).fetch(&mut conn).next().await?.unwrap().get(0);
    println!("{:?}", insert_id);

    drop(conn);
四、查詢sql結果集轉化成struct

1、定義一個查詢的struct

#[derive(Debug)]
struct User {
    id: i32,
    username: String,
}

impl<'c> sqlx::FromRow<'c, MySqlRow<'c>> for User {
    fn from_row(row: &MySqlRow<'c>) -> Result<Self, Error> {
        Ok(User {
            id: row.get("id"),
            username: row.get("username"),
        })
    }
}

2、使用fetch獲取結果集Vec<User>流Stream數據

    let sql = "select id, username from t_user where id < ?";
    // use tokio::stream::StreamExt;
    let mut stream = sqlx::query_as::<_, User>(sql).bind(3).fetch(&pool);
    while let Some(user) = stream.try_next().await? {
        println!("{:?}", user);
    }

3、使用fetch_one獲取一條結果集User

    let sql = "select id, username from t_user where id < ?";
    let user: User = sqlx::query_as::<_, User>(sql).bind(3).fetch_one(&pool).await?;
    println!("{:?}", user);

4、使用fetch_all獲取所有的結果集Vec<User>

    let sql = "select id, username from t_user where id < ?";
    let users: Vec<User> = sqlx::query_as::<_, User>(sql).bind(3).fetch_all(&pool).await?;
    println!("{:?}", users);
五、事務處理
    let mut conn = pool.begin().await?;

    let sql = r#"insert into t_user (username, password) value (?, ?)"#;
    sqlx::query(sql).bind("wy").bind("123456").execute(&mut conn).await?;

    conn.commit().await?;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章