rust使用sqlx示例
这篇文章介绍了如何使用Rust的sqlx库操作MySQL数据库,主要内容包括: 项目结构:展示了完整的Rust代码实现用户添加功能,包含用户实体定义、仓储接口和持久化层实现。 关键技术点: 使用async-trait实现异步特性 通过dotenv读取环境变量配置 使用MySqlPool管理数据库连接池 实现基本的CRUD操作(示例演示了添加用户) 运行效果:展示了程序执行后的数据库插入结果。 项目
概要
rust使用sqlx对mysql数据库进行添加操作示例,以及sqlx cli使用方法(sqlx cli是sqlx的数据管理工具提供数据库管理和迁移支持)
完整代码
use std::env;
use async_trait::async_trait;
use sqlx::Error;
use sqlx::mysql::MySqlPool;
pub struct UserDo {
pub id:u64,
pub username:String,
pub email:String,
pub password:String,
}
impl UserDo {
pub fn new (username:String, email:String, password:String) -> Self {
Self{
id:0,
username,
email,
password
}
}
}
#[async_trait]
pub trait UserRepo: Send + Sync {
async fn add_user(&self, _: UserDo) ->Result<UserDo,Error>;
}
pub struct UserPersistence {
pub pool:MySqlPool,
}
impl UserPersistence {
pub async fn new() -> Result<Self,Error> {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
println!("DATABASE_URL: {}", &database_url);
let pool = MySqlPool::connect(&database_url).await?;
Ok(Self { pool })
}
}
#[async_trait]
impl UserRepo for UserPersistence {
async fn add_user(&self, user: UserDo) -> Result<UserDo, Error>{
let result = sqlx::query!(
"INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
user.username,
user.email,
user.password
)
.execute(&self.pool)
.await?;
let user_id = result.last_insert_id();
let inserted_user: UserDo = sqlx::query_as!(
UserDo,
"SELECT id, username, email, password FROM users WHERE id = ?",
user_id
)
.fetch_one(&self.pool)
.await?;
Ok(inserted_user)
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv().ok();
// 初始化数据库连接池
let user_service = UserPersistence::new().await?;
// 创建新用户对象
let user_do = UserDo::new("sssacsa".into(), "889999@qq.com".into(), "opass".into());
// 添加用户并处理结果
match user_service.add_user(user_do).await {
Ok(inserted_user) => {
println!("User added successfully: ID {}", inserted_user.id);
Ok(())
}
Err(e) => {
eprintln!("Failed to add user: {}", e);
Err(e.into())
}
}
}
项目结构
运行效果
项目运行效果
执行命令
cargo run
执行结果展示
项目介绍
包引用介绍
该示例主要用到的包就配置文件如下
- async-trait:提供异步支持
- dotenv:提供配置文件读取支持
- sqlx :提供数据库交互支持
- tokio:Rust 编程语言的异步运行时
[dependencies]
async-trait = "0.1.89"
dotenv = "0.15.0"
sqlx = { version = "0.8.6",features = ["mysql","runtime-async-std-native-tls"] }
tokio = { version = "1.47.1", features = ["rt", "rt-multi-thread", "macros"] }
项目中引入这些包,
use std::env;
use async_trait::async_trait;
use sqlx::Error;
use sqlx::mysql::MySqlPool;
用户实体
以下do实体是用于与数据库交互的实体,需要注意的是在实际企业级应用开发中实体肯定不会这么简单,这里只是为了给初学者示例,方便大家理解所以字段相对较少。
pub struct UserDo {
pub id:u64,
pub username:String,
pub email:String,
pub password:String,
}
impl UserDo {
pub fn new (username:String, email:String, password:String) -> Self {
Self{
id:0,
username,
email,
password
}
}
}
上面的代码 impl UserDo
中 new
函数是结构体(UserDo)的有参构造
方便后面给结构体赋值。
定义仓储接口
该接口主要实现对用户这个模块的新增功能
#[async_trait]
pub trait UserRepo: Send + Sync {
async fn add_user(&self, _: UserDo) ->Result<UserDo,Error>;
}
持久化层
持久化层主要是负责对仓储接口的实现
pub struct UserPersistence {
pub pool:MySqlPool,
}
impl UserPersistence {
pub async fn new() -> Result<Self,Error> {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
println!("DATABASE_URL: {}", &database_url);
let pool = MySqlPool::connect(&database_url).await?;
Ok(Self { pool })
}
}
#[async_trait]
impl UserRepo for UserPersistence {
async fn add_user(&self, user: UserDo) -> Result<UserDo, Error>{
let result = sqlx::query!(
"INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
user.username,
user.email,
user.password
)
.execute(&self.pool)
.await?;
let user_id = result.last_insert_id();
let inserted_user: UserDo = sqlx::query_as!(
UserDo,
"SELECT id, username, email, password FROM users WHERE id = ?",
user_id
)
.fetch_one(&self.pool)
.await?;
Ok(inserted_user)
}
}
上面这段代码有点多,不用急咱们分段来解释
首先这段代码,这里可以看到我们也是定义了一个结构体实现了它的构造方法
,
但是与上面不同的是我们的构造方法并没有传入参数,这里其实我们读取的是环境变量,.env文件。这里使用到的是rust的一个插件,dotenv;你可以把这里理解为像C#读取appsetting.json文件一样。
MySqlPool是一个sqlx提供的mysql连接池类型,
它的作用就是读取到配置文件中的数据库连接字符串。创建连接池
pub struct UserPersistence {
pub pool:MySqlPool,
}
impl UserPersistence {
pub async fn new() -> Result<Self,Error> {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
println!("DATABASE_URL: {}", &database_url);
let pool = MySqlPool::connect(&database_url).await?;
Ok(Self { pool })
}
}
注意:.env文件文件是自己创建的文件,与Cargo.toml同级
DATABASE_URL=mysql://用户名:密码@localhost/库名
下面这段代码是实现上面定义的用户仓储实现持久化到数据库中,传入的是一个UserDo实体,返回值是新插入的这个UserDo,如果报错的话会返回Error信息
#[async_trait]
impl UserRepo for UserPersistence {
async fn add_user(&self, user: UserDo) -> Result<UserDo, Error>{
let result = sqlx::query!(
"INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
user.username,
user.email,
user.password
)
.execute(&self.pool)
.await?;
let user_id = result.last_insert_id();
let inserted_user: UserDo = sqlx::query_as!(
UserDo,
"SELECT id, username, email, password FROM users WHERE id = ?",
user_id
)
.fetch_one(&self.pool)
.await?;
Ok(inserted_user)
}
}
应用层
在main函数中我进行方法调用
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv().ok();
// 初始化数据库连接池
let user_service = UserPersistence::new().await?;
// 创建新用户对象
let user_do = UserDo::new("sssacsa".into(), "889999@qq.com".into(), "opass".into());
// 添加用户并处理结果
match user_service.add_user(user_do).await {
Ok(inserted_user) => {
println!("User added successfully: ID {}", inserted_user.id);
Ok(())
}
Err(e) => {
eprintln!("Failed to add user: {}", e);
Err(e.into())
}
}
}
接下来咱们来解释一下上面这段代码:
dotenv::dotenv().ok();
这句代码看起来很突兀对吧,但是它是不能缺少的,它的作用是把 .env 文件里的 KEY=value 逐行读出来,塞进当前进程的「环境变量表」里,之后 std::env::var(“KEY”) 就能拿到值。如果这段代码没有我们上面读取数据库连接字符串哪里就会报错。
match user_service.add_user(user_do).await...
这段代码的作用是接受方法返回值,还记得我们add_user函数中使用的返回类型是什么吗?是Result<UserDo, Error>;Result有两个变体,一个是用户实体,一个是错误实体。
我们使用match表达式就相当于c# 中的if判断,
如果方法执行成功了咱们再Ok里就接收它的返回值,然后打印,如果失败了就程序panic直接恐慌,程序直接死给你看然后把错误信息给提示出来。
sqlx cli的使用
安装
首先执行进行安装;注意:这里我使用的是mysql所以代码最后填写的是mysql,如果你使用的是pgsql,这里需要修改
cargo install sqlx-cli --no-default-features --features native-tls,mysql
当安装完成后我们可以在项目控制台执行迁移命令;当执行完成之后会在项目中生成一个migrations文件夹,里面有我们创建的迁移脚本create_users_table ;注意:create_users_table 这个是可以自定义
的迁移脚本文件名。
sqlx migrate add create_users_table
这里生成的迁移脚本是空的,需要自己手动写
当迁移脚本添加好了之后 执行以下命令运行迁移脚本
sqlx migrate run
执行结束后我们可以在库里看到有一点变化,sqlx会创建一个迁移记录表
源代码下载
小结
以上就是我今天给大家分享sqlx的简单使用示例,希望对大家有所帮助。
更多推荐
所有评论(0)