Rust 数据库操作:Sea-orm

我爱海鲸 2024-07-16 17:34:43 rust学习

简介orm、对象关系映射、分页查询

sea_orm - Rust (docs.rs)

Rust语言从入门到精通系列 - SeaORM框架实战(数据库DML篇) - 掘金 (juejin.cn)

2027-07-16 start:

Database Connection | SeaORM  An async & dynamic ORM for Rust (sea-ql.org)

项目截图:

整个项目的名称:seaorm_test

二进制项目名:tester

lib项目名:tester-lib(暂时是一个空crate)

总Cargo.toml:

[workspace]

resolver = "2"

members = [
    "tester"
, "tester-lib"]

tester的Cargo.toml:

[package]
name = "tester"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

sea-orm = { version = "0.12.15", features = [ "sqlx-mysql", "runtime-tokio-rustls", "macros" ] }
tokio = {version="1.38.0",features=["full"]}


[lib]
name = "db_lib"
path = "src/db_lib/mod.rs"

tester-lib的Cargo.toml:

[package]
name = "tester-lib"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

main.rs:

use std::error::Error;

use sea_orm::{entity::prelude::*, Database};

use db_lib::wallpaper_type_model::Entity as WallpaperType;

 
 #[tokio::main]
async fn main()->Result<(),Box<dyn Error>> {
    let db: DatabaseConnection = Database::connect("protocol://username:password@host/database").await?;
    let res =WallpaperType::find().all(&db).await?;


    for wallpaper_type in res {
        let name = wallpaper_type.type_name.unwrap();
        println!("{:?}",name);
    }

    Ok(())
}

mod.rs:

pub mod wallpaper_type_model;

wallpaper_type_models.rs:

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "wallpaper_type")]
pub struct Model  {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub type_name: Option<String>,
    pub type_url: Option<String>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {

}

impl ActiveModelBehavior for ActiveModel {}

分页的用法 start:

安装rust二进制库:Using sea-orm-cli | SeaORM An async & dynamic ORM for Rust (sea-ql.org)

cargo install sea-orm-cli

sea-orm-cli generate entity -u mysql://root:123456@127.0.0.1:3306/test -o entity/src --expanded-format

执行完上面的代码后就能够在entity/src下生成实体代码了,然后把生成的代码复制到db_lib目录中,之前的代码就可以删除了

然后我们在一个实体中写测试代码:

wallpaper_detail.rs:

//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15

use sea_orm::entity::prelude::*;

#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;

impl EntityName for Entity {
    fn table_name(&self) -> &str {
        "wallpaper_detail"
    }
}

#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)]
pub struct Model {
    pub id: i32,
    pub wallpaper_name: String,
    pub wallpaper_list_url: String,
    pub wallpaper_type: i32,
    pub remark: String,
    pub wallpaper_detail_url: String,
    pub wallpaper_detail_click_url: String,
    pub wallpaper_list_width: Option<i32>,
    pub wallpaper_list_height: Option<i32>,
    pub wallpaper_detail_width: Option<i32>,
    pub wallpaper_detail_height: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
    Id,
    WallpaperName,
    WallpaperListUrl,
    WallpaperType,
    Remark,
    WallpaperDetailUrl,
    WallpaperDetailClickUrl,
    WallpaperListWidth,
    WallpaperListHeight,
    WallpaperDetailWidth,
    WallpaperDetailHeight,
}

#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
    Id,
}

impl PrimaryKeyTrait for PrimaryKey {
    type ValueType = i32;
    fn auto_increment() -> bool {
        true
    }
}

#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {}

impl ColumnTrait for Column {
    type EntityName = Entity;
    fn def(&self) -> ColumnDef {
        match self {
            Self::Id => ColumnType::Integer.def(),
            Self::WallpaperName => ColumnType::String(Some(90u32)).def(),
            Self::WallpaperListUrl => ColumnType::String(Some(255u32)).def(),
            Self::WallpaperType => ColumnType::Integer.def(),
            Self::Remark => ColumnType::String(Some(255u32)).def(),
            Self::WallpaperDetailUrl => ColumnType::String(Some(255u32)).def(),
            Self::WallpaperDetailClickUrl => ColumnType::String(Some(255u32)).def(),
            Self::WallpaperListWidth => ColumnType::Integer.def().null(),
            Self::WallpaperListHeight => ColumnType::Integer.def().null(),
            Self::WallpaperDetailWidth => ColumnType::Integer.def().null(),
            Self::WallpaperDetailHeight => ColumnType::Integer.def().null(),
        }
    }
}

impl RelationTrait for Relation {
    fn def(&self) -> RelationDef {
        panic!("No RelationDef")
    }
}

impl ActiveModelBehavior for ActiveModel {}


#[cfg(test)]
mod tests {
    use std::error::Error;

    use sea_orm::{Condition, Database, DatabaseConnection, EntityTrait, PaginatorTrait, QueryFilter};

    use crate::prelude;

    use super::*;

    #[tokio::test]
    async fn test_detail() ->Result<(),Box<dyn Error>> {
        let db: DatabaseConnection = Database::connect("mysql://root:123456@127.0.0.1:3306/test").await?;

        let s = String::from("%迪丽%");

        let mut  page = 5;

        let page_size = 10;

        let res =  prelude::WallpaperDetail::find()
        .filter(
            Condition::all()
                .add(crate::wallpaper_detail::Column::WallpaperName.like(&s))
        )
        .paginate(&db, page_size);


        let page_num = res.num_pages().await?;
        

        if page > page_num || page < 1 {
            page = 1;
        }


        let limit = page -1;

        let vecs =  res.fetch_page(limit).await?;

        for v in vecs {
            println!("{:?}:{:?}",v.wallpaper_name,v.wallpaper_detail_url) 
        }
    

        // 当前页码
        println!("当前页码:{:?}",page);
        // 总数量
        println!("总数量:{:?}",res.num_items().await?);
        // 页面数量
        println!("页面数量:{:?}",page_num);

        Ok(())
    }
}

main.rs:

use std::error::Error;

use db_lib::prelude;
use sea_orm::{entity::prelude::*, Condition, Database, DbBackend, QueryTrait};


 
 #[tokio::main]
async fn main()->Result<(),Box<dyn Error>> {
    let db: DatabaseConnection = Database::connect("").await?;
    // 查询所有数据
    // let res =WallpaperType::find().all(&db).await?;
    // for wallpaper_type in res {
    //     let name = wallpaper_type.type_name.unwrap();
    //     println!("{:?}",name);
    // }

    let s = String::from("%美女%");

    let mut  res = prelude::WallpaperDetail::find()
    .filter(
        Condition::all()
            .add(db_lib::wallpaper_detail::Column::WallpaperName.like(&s))
    )
    .paginate(&db, 100);

    println!("{}",prelude::WallpaperDetail::find()
    .filter(
        Condition::all()
            .add(db_lib::wallpaper_detail::Column::WallpaperName.like(&s))
    )
    
    .build(DbBackend::MySql)
    .to_string()
);

    

    // println!("{:?}",res);

    if let Some(values) = res.fetch_and_next().await? {
        for v in values {
           println!("{:?}:{:?}",v.wallpaper_name,v.wallpaper_detail_url) 
        }  
    }

    // 总数量
    println!("{:?}",res.num_items().await?);
    // 页面数量
    println!("{:?}",res.num_pages().await?);


    Ok(())
}

end

 

end

你好:我的2025