簡介
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#"update course 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<NaiveDate>,
}
以上程式碼輸出
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,
),
},
]
程式碼
https://gitee.com/naylor_personal/rust-actix/tree/master/workspace/db