• 【rust】8、连接数据库:sqlx


    sqlx 是 rust 的数据库访问工具, 本身并不是 orm,但常见的 orm 都是基于它实现的。其有如下特点:

    • 支持异步,适合高并发
    • 编译时检查:cargo build 时检查执行 sql,校验响应值
    • 支持多数据库:mysql、pg、sqlite 等
    • 支持主流 rust 运行时:tokio、async-std、actix、native-tls、rustls等
    • 内置连接池

    一、数据库、依赖、环境变量

    本文操作 pg,首先建表

    DROP TABLE IF EXISTS course;
    CREATE TABLE course (
        id INT8 NOT NULL,
        teacher_id INT4 NOT NULL,
        name VARCHAR(255) NOT NULL,
        time DATE DEFAULT NOW()
    );
    INSERT INTO course VALUES (1, 11, 'cml', '2022-03-25');
    INSERT INTO course VALUES (2, 22, 'cc', '2022-03-25');
    INSERT INTO course VALUES (3, 33, 'mm', '2022-03-25');
    ALTER TABLE course ADD CONSTRAINT course_pkey PRIMARY KEY (id);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    用 cargo new 新建项目,添加依赖:

    cargo add sqlx -F postgres -F runtime-tokio-rustls -F macros -F chrono
    cargo add dotenv # 环境变量工具。本例中将使用此工具处理数据库连接字符串。
    cargo add chrono -F serde # 时间工具
    cargo add serde -F derive # 序列化
    cargo add actix-web # actix 运行时
    cargo add actix-rt # actix 运行时
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    环境变量

    数据库地址可以放在配置文件里,例如在根目录新建一个 .env 文件,内容如下:

    DATABASE_URL=postgres://cml:123456@192.168.1.239:5432/postgres
    
    • 1

    二、增删改查

    2.1 完整示例

    • dotenv().ok():在访问环境变量之前检查一下,防止因读取环境变量失败导致程序 panic。
    • env::var(“DATABASE_URL”):读取环境变量文件中的数据库连接字符串
    • PgPoolOptions::new().connect():实例化一个数据库连接池
    • sqlx::query!(“sql”) .fetch_all(&pool):执行sql语句

    工程目录结构:

    │  .env
    │  Cargo.toml 
    ├─src
    │      main.rs
    
    • 1
    • 2
    • 3
    • 4

    示例代码:

    use chrono::NaiveDate;
    use dotenv::dotenv;
    use sqlx::postgres::PgPoolOptions;
    use std::env;
    
    #[derive(Debug)]
    pub struct Course {
        pub id: i64,
        pub teacher_id: i32,
        pub name: String,
        pub time: Option<NaiveDate>,
    }
    
    #[actix_rt::main]
    async fn main() -> Result<(), sqlx::Error> {
        println!("Hello, world!");
        dotenv().ok();
        读取所有的环境变量
        // for (key, value) in env::vars() {
        //     println!("环境变量内容:{}: {}", key, value);
        // }
        let connection_str = env::var("DATABASE_URL")
            .expect("数据库连接字符串获取失败,请检查env文件是否已配置数据库连接字符串");
        println!("数据库连接字符串是:{}", connection_str);
        let pool = PgPoolOptions::new()
            .max_connections(5)
            .connect(&connection_str)
            .await?;
        println!("db_pool is : {:?}", pool);
        //查询所有
        let list = sqlx::query!("select * from course")
            .fetch_all(&pool)
            .await?;
        let mut vec = vec![];
        for row in list {
            vec.push(Course {
                id: row.id,
                teacher_id: row.teacher_id,
                name: row.name,
                time: row.time,
            })
        }
        println!("数据库中的所有数据:{:#?}", vec);
        //查询单个
        let list2 = sqlx::query!(r#"select * from course where id = $1"#, 1)
            .fetch_all(&pool)
            .await?;
        let mut vec2 = vec![];
        for row in list2 {
            vec2.push(Course {
                id: row.id,
                teacher_id: row.teacher_id,
                name: row.name,
                time: row.time,
            })
        }
        println!("查询单个{:#?}", vec2);
        // 增加
        let insert = sqlx::query!(
            r#"INSERT INTO course VALUES ($1, $2, $3)"#,
            100000,
            11,
            "gg"
        )
        .fetch_all(&pool)
        .await?;
        // 更新
        let update = sqlx::query!(r#"update course set name=$1"#, "ogg")
            .fetch_all(&pool)
            .await?;
        Ok(())
    }
    
    // cargo r
    Hello, world!
    数据库连接字符串是:postgres://postgres:pass@ip:5432/postgres
    db_pool is : Pool { size: 1, num_idle: 1, is_closed: false, options: PoolOptions { max_connections: 5, min_connections: 0, connect_timeout: 30s, max_lifetime: Some(1800s), idle_timeout: Some(600s), test_before_acquire: true } }
    数据库中的所有数据:[
        Course {
            id: 1,
            teacher_id: 11,
            name: "cml",
            time: Some(
                2022-03-25,
            ),
        },
        Course {
            id: 2,
            teacher_id: 22,
            name: "cc",
            time: Some(
                2022-03-25,
            ),
        },
        Course {
            id: 3,
            teacher_id: 33,
            name: "mm",
            time: Some(
                2022-03-25,
            ),
        },
    ]
    查询单个[
        Course {
            id: 1,
            teacher_id: 11,
            name: "cml",
            time: Some(
                2022-03-25,
            ),
        },
    ]
    
    // 执行完时,查询数据库如下:
    postgres=# select * from course;
       id   | teacher_id | name |    time
    --------+------------+------+------------
          1 |         11 | ogg  | 2022-03-25
          2 |         22 | ogg  | 2022-03-25
          3 |         33 | ogg  | 2022-03-25
     100000 |         11 | ogg  | 2024-02-21
    (4 rows)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    参考:https://www.cnblogs.com/Naylor/p/16062584.html

    2.2 query

    let sql = format!(r#"DROP TABLE IF EXISTS {}"#, tmp_table_name);
    let r = sqlx::query(&sql).execute(&pool).await?;
    println!("sql: {} r: {:?}", sql, r);
    
    • 1
    • 2
    • 3
  • 相关阅读:
    OpenCV算法库
    Linux操作系统-线程同步与互斥
    java中如何使用字段对对象数组进行排序
    四、thymeleaf注释
    关于 Elasticsearch 内存占用及分配
    PDF格式分析(八十)——弹出、文件附件注释(Popup、FileAttachment)
    java计算机毕业设计html5大众汽车网站MyBatis+系统+LW文档+源码+调试部署
    Spark-机器学习(3)回归学习之线性回归
    XView 架构升级之路
    kotlin修饰符const的含义
  • 原文地址:https://blog.csdn.net/jiaoyangwm/article/details/136224654