【从零开始的rust web开发之路 三】orm框架sea-orm入门使用教程

2024-02-01 05:36

本文主要是介绍【从零开始的rust web开发之路 三】orm框架sea-orm入门使用教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【从零开始的rust web开发之路 三】orm框架sea-orm入门使用教程


文章目录

  • 前言
  • 一、引入依赖
  • 二、创建数据库连接
    • 简单链接
    • 连接选项
    • 开启日志调试
  • 三、生成实体
    • 安装sea-orm-cli
    • 创建数据库表
    • 使用sea-orm-cli命令生成实体文件代码
  • 四、增删改查实现
    • 新增数据
    • 主键查找
    • 条件查找
      • 查找用户名是admin的一条用户
      • 查找地址是郑州的所有用户
      • 查找地址是郑州并且用户名包含admin的所有用户
      • 分页查找
    • 修改数据
    • 删除数据
    • 数据库事务操作
  • 总结

前言

前两篇文件主要降了axum相关使用,这篇文章来讲讲orm相关框架。目前rust orm相关框架不多,比较主流的是sqlx,本文介绍的框架实在此基础上封装的一层,sql-orm同样也支持rust异步。

一、引入依赖

sea-orm = { version = "0.12", features = [ <DATABASE_DRIVER>, <ASYNC_RUNTIME>, "macros" ] }  #DATABASE_DRIVERASYNC_RUNTIME参数需要替换

DATABASE_DRIVER参数

  • sqlx-mysql-SQLx的MySQL
  • sqlx-postgres-SQLx
  • PostgreSQL的 sqlx-sqlite

ASYNC_RUNTIME参数

  • runtime-async-std-native-tls
  • runtime-tokio-native-tls
  • runtime-async-std-rustls
  • runtime-tokio-rustls
    这里我们选择引入tokio异步支持的,还要引入tokio
[dependencies]
sea-orm = { version = "0.12", features = [ "sqlx-mysql", "runtime-tokio-native-tls", "macros" ] }
tokio = { version = "1.35.1", features = ["full"] }

二、创建数据库连接

简单链接

let db: DatabaseConnection = Database::connect("protocol://username:password@host/database").await?;

举例子mysql数据库连接

   let db: DatabaseConnection = Database::connect("mysql://root:root@127.0.0.1:3307/test").await.unwrap();

后续查询选相关操作每次调用DatabaseConnection ,都会从池中获取和释放连接。
连接别的数据库可以看官方文档https://www.sea-ql.org/SeaORM/docs/next/install-and-config/connection/

连接选项

若要配置连接,请使用 ConnectOptions 接口
let mut opt = ConnectOptions::new("mysql://root:root@127.0.0.1:3307/test");
opt.max_connections(100).min_connections(5).connect_timeout(Duration::from_secs(8)).acquire_timeout(Duration::from_secs(8)).idle_timeout(Duration::from_secs(8)).max_lifetime(Duration::from_secs(8)).sqlx_logging(true).sqlx_logging_level(log::LevelFilter::Info).set_schema_search_path("my_schema"); // Setting default PostgreSQL schemalet db = Database::connect(opt).await?;

可以看ConnectOptions接口文档https://docs.rs/sea-orm/0.12.12/sea_orm/struct.ConnectOptions.html

开启日志调试

开发阶段需要打印相关日志,可以开启调试模式
features当中多一个[“debug-print”]

[dependencies]
sea-orm = { version = "0.12", features = [ "sqlx-mysql", "runtime-tokio-native-tls", "macros" ,"debug-print","with-chrono"] }
tokio = { version = "1.35.1", features = ["full"] }
chrono = "0.4.33"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18",features = ["env-filter","time","local-time", ]}

然后需要执行一段初始化tracing-subscriber代码

    // 设置全局日志级别为 infolet env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"))//单独设置sea_orm.add_directive("sea_orm::driver=debug".parse().unwrap())//关闭sqlx自带的日志.add_directive("sqlx::query=off".parse().unwrap());

三、生成实体

安装sea-orm-cli

运行命令

cargo install sea-orm-cli

创建数据库表

CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT,`username` varchar(32) NOT NULL COMMENT '用户名称',`birthday` datetime DEFAULT NULL COMMENT '生日',`sex` char(1) DEFAULT NULL COMMENT '性别',`address` varchar(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb3

使用sea-orm-cli命令生成实体文件代码

在项目文件夹下运行命令,-o 是输出文件目录。相关参数配置可看文档https://www.sea-ql.org/SeaORM/docs/next/generate-entity/sea-orm-cli/

sea-orm-cli generate entity -u mysql://root:root@127.0.0.1:3307/test -o src/entity

在这里插入图片描述
在main文件加入entity模块即可。
生成的文件内容
在这里插入图片描述

在这里插入图片描述
指定表名

#[sea_orm(table_name = "cake", schema_name = "public")]
pub struct Model { ... }

指定列名

#[sea_orm(column_name = "name")]
pub name: String

四、增删改查实现

新增数据

先了解ActiveValue和ActiveModel
use entity::user::ActiveModel as UserModel;
let user: UserModel =  UserModel{id: ActiveValue::NotSet,username: ActiveValue::Set("你好".to_owned()),birthday: ActiveValue::Set(Some(Local::now().naive_local())),sex: ActiveValue::Set(Some("1".to_owned())),address: ActiveValue::Set(Some("address".to_owned())),};

这里我们创建UserModel的ActiveModel模型,里面的值是ActiveValue类型,NotSet是不设置值。
创建ActiveModel方法还有别的,比如通过JSON字符,具体的可以看文档https://www.sea-ql.org/SeaORM/docs/next/basic-crud/insert/#convert-activemodel-back-to-model
然后执行插入方法,具体代码如下

use chrono::{ Local};
use sea_orm::{ActiveModelTrait, ActiveValue, Database, DatabaseConnection, IntoActiveModel};pub mod entity;
use entity::user::Entity as UserDao;
use entity::user::ActiveModel as UserModel;
use entity::user::Model as Model;
#[tokio::main]
async fn main(){let db: DatabaseConnection = Database::connect("mysql://root:root@127.0.0.1:3307/test").await.unwrap();let user: UserModel =  UserModel{id: ActiveValue::NotSet,username: ActiveValue::Set("你好".to_owned()),birthday: ActiveValue::Set(Some(Local::now().naive_local())),sex: ActiveValue::Set(Some("1".to_owned())),address: ActiveValue::Set(Some("address".to_owned())),};
/*    let user: Model = Model{id: 1,username: "admin".to_string(),birthday: Some(Local::now().naive_local()),sex: Some("1".to_owned()),address: Some("address".to_owned()),};let active_model = user.into_active_model();*/let result = user.insert(&db).await.unwrap();println!("插入成功!:{:?}",result);
}

多个插入可以调用上述代码UserDao中的insert_many方法,传入ActiveModel数组

主键查找

use entity::user::Entity as UserDao;let option = UserDao::find_by_id(1).one(&db).await.unwrap();match option {None => {}Some(user) => println!("查询成功!:{:?}",user)}

条件查找

查找用户名是admin的一条用户

use crate::entity::user;use entity::user::Entity as UserDao;let result = UserDao::find().filter(user::Column::Username.eq("admin")).one(&db).await.unwrap();match result {None => {}Some(user) => println!("查询成功!:{:?}",user)}

查找地址是郑州的所有用户

    use crate::entity::user;use entity::user::Entity as UserDao;let result = UserDao::find().filter(user::Column::Address.eq("郑州")).all(&db).await.unwrap();println!("查询成功!:{:?}",result)

查找地址是郑州并且用户名包含admin的所有用户

    use crate::entity::user;use entity::user::Entity as UserDao;let result = UserDao::find().filter(Condition::all().add(user::Column::Address.eq("郑州")).add(user::Column::Username.like("%admin%"))).all(&db).await.unwrap();println!("查询成功!:{:?}",result)

分页查找

 
use crate::entity::user;use entity::user::Entity as UserDao;let mut paginator = UserDao::find().filter(Condition::all().add(user::Column::Address.eq("郑州")).add(user::Column::Username.like("%admin%"))).paginate(&db,50);//paginate(&db,50)此处第二个参数表示设置单页数量,此方法会返回Paginator对象。while let Some(user) = paginator.fetch_and_next().await.unwrap() {//循环从paginate取数据,每次取50条,页数加一,直到没有数据println!("查询成功!:{:?}",user)}

如果直接获取第几页数据怎么做,下面有方法

    use crate::entity::user;use entity::user::Entity as UserDao;let mut paginator = UserDao::find().filter(Condition::all().add(user::Column::Address.eq("郑州")).add(user::Column::Username.like("%admin%"))).paginate(&db,50);//此方法可直接取具体页数,注意是从零开始,需要前端页数加一let result = paginator.fetch_page(0).await;match result{Ok(vec_user) => {println!("{:?}", vec_user)}Err(_) => {}}

修改数据

修改主键为1的用用户名

    use entity::user::Entity as UserDao;let user = UserDao::find_by_id(1).one(&db).await.unwrap().unwrap();let mut active_model = user.into_active_model();active_model.username = ActiveValue::Set("修改后的用户名".to_owned());active_model.update(&db).await.unwrap();

如果想强制更新某个字段可以调用。

active_model.reset(user::Column::Address); //这样更新时字段就会强制带上,可以实现把字段置空

删除数据

很简单

    use entity::user::Entity as UserDao;let res = UserDao::delete_by_id(1).exec(&db).await.unwrap();

或者还有一种方法

    use entity::user::Entity as UserDao;let res = UserDao::find_by_id(1).one(&db).await.unwrap().unwrap();let active_model = res.into_active_model();active_model.delete(&db).await.unwrap();

数据库事务操作

可以手动调用db的begin和commit方法,以下是官方例子

let txn = db.begin().await?;bakery::ActiveModel {name: Set("SeaSide Bakery".to_owned()),profit_margin: Set(10.4),..Default::default()
}
.save(&txn)
.await?;bakery::ActiveModel {name: Set("Top Bakery".to_owned()),profit_margin: Set(15.0),..Default::default()
}
.save(&txn)
.await?;txn.commit().await?;

总结

以上就是sea-orm入门使用教程,更具体的可以查看sea-orm官方文档https://www.sea-ql.org/SeaORM/docs/index/。后续我可能会再出一篇sea-orm的高级使用教程

这篇关于【从零开始的rust web开发之路 三】orm框架sea-orm入门使用教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/666225

相关文章

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(