Rust-Sqlx极简教程

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

  • 异步:原生就支持异步,在并发性高的场合能够得到更好的支持
  • 编译时检查查询:sqlx可以在 cargo build 的时候检查执行sql和响应值
  • 多数据库支持:PostgresSQL,MySql,SqlLite,MSSql,MariaDB
  • 多运行时支持:支持主流 rust 运行时。async-std,tokio,actix,native-tls,rustls
  • 内置连接池,支持查询缓存
不足 sqlx 不是 orm 框架
实践
本例将使用 sqlx 访问 postgressql 数据库,实现简单的增删改查功能
数据库 数据库采用 postgreSQL,初始建表语句如下:
-- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS "public"."course"; CREATE TABLE "public"."course" ( "id" int8 NOT NULL, "teacher_id" int4 NOT NULL, "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "time" date DEFAULT now() ) ; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO "public"."course" VALUES (1, 11, 'cml', '2022-03-25'); INSERT INTO "public"."course" VALUES (2, 22, 'cc', '2022-03-25'); INSERT INTO "public"."course" VALUES (3, 33, 'mm', '2022-03-25'); -- ---------------------------- -- Primary Key structure for table course -- ---------------------------- ALTER TABLE "public"."course" ADD CONSTRAINT "course_pkey" PRIMARY KEY ("id");

依赖 使用 cargo new 一个新的 project ,并在 toml 中添加如下依赖:
  • sqlx:数据库访问工具
  • dotenv:环境变量工具。本例中将使用此工具处理数据库连接字符串。此工具除了会加载文件中的配置信息,还会加载windows操作系统中的环境变量信息,如 JAVA_HOME 等。
  • chrono:时间和日期工具
  • serde:序列化和反序列化工具
  • actix-web&actix-rt:actix 运行时
[dependencies] actix-rt="2.6.0" actix-web="3.3.3" serde={version="1.0.134",features=["derive"]} chrono={version="0.4.19",features=["serde"]} dotenv="0.15.0" sqlx={version="0.5.10",features=["postgres","runtime-tokio-rustls","macros","chrono"]}

环境变量 一般来说,数据库连接字符串都不会硬编码到程序代码中,需要有一个类似配置文件的文件,将连接信息放文件中, 运行时从文件加载数据库连接信息。
根目录新建一个 .env 的文件,并在里面配置数据库连接字符串:
DATABASE_URL=postgres://cml:123456@192.168.1.239:5432/rust_sqlx

其中, rust_sqlx 为数据库实例的名称
CRUD 说明
在 main 中编写简单的 crud 示例。
  • dotenv().ok():在访问环境变量之前检查一下,防止因读取环境变量失败导致程序恐慌。
  • env::var("DATABASE_URL"):读取环境变量文件中的数据库连接字符串
  • PgPoolOptions::new().connect():实例化一个数据库连接池
  • sqlx::query!("sql") .fetch_all(&pool):执行sql语句
工程目录结构
│.env │Cargo.toml │course.sql │README.md │tree.txt │ ├─src │main.rs

示例代码
use actix_web::{web, App, HttpServer}; use chrono::NaiveDate; use dotenv::dotenv; use sqlx::postgres::PgPoolOptions; use std::env; #[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("postgres://cml:123456@192.168.1.239:5432/rust_sqlx") .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#"updatecourse set name=$1"#, "ogg") .fetch_all(&pool) .await?; Ok(()) } #[derive(Debug)] pub struct Course { pub id: i64, pub teacher_id: i32, pub name: String, pub time: Option, }

以上代码输出
Hello, world! 数据库连接字符串是:postgres://cml:123456@192.168.1.239:5432/rust_sqlx 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: "ogg", time: Some( 2022-03-25, ), }, Course { id: 2, teacher_id: 22, name: "ogg", time: Some( 2022-03-25, ), }, Course { id: 3, teacher_id: 33, name: "ogg", time: Some( 2022-03-25, ), }, Course { id: 100000, teacher_id: 11, name: "ogg", time: Some( 2022-03-26, ), }, ] 查询单个[ Course { id: 1, teacher_id: 11, name: "ogg", time: Some( 2022-03-25, ), }, ]

代码 【Rust-Sqlx极简教程】https://gitee.com/naylor_personal/rust-actix/tree/master/workspace/db
引用
  • https://crates.io/crates/sqlx

    推荐阅读