Utilizando Bancos de Dados

Diesel

use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool, PoolError, PooledConnection};
use once_cell::sync::OnceCell;
use salvo::prelude::*;

const DB_URL: &str = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world";
type PgPool = Pool<ConnectionManager<PgConnection>>;

static DB_POOL: OnceCell<PgPool> = OnceCell::new();

fn connect() -> Result<PooledConnection<ConnectionManager<PgConnection>>, PoolError> {
    DB_POOL.get().unwrap().get()
}
fn build_pool(database_url: &str, size: u32) -> Result<PgPool, PoolError> {
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    diesel::r2d2::Pool::builder()
        .max_size(size)
        .min_idle(Some(size))
        .test_on_check_out(false)
        .idle_timeout(None)
        .max_lifetime(None)
        .build(manager)
}

fn main() {
    DB_POOL
        .set(build_pool(&DB_URL, 10).expect(&format!("Error connecting to {}", &DB_URL)))
        .ok();
}

#[handler]
async fn show_article(req: &mut Request, res: &mut Response) -> Result<(), Error> {
    let id: i64 = req.param::<i64>("id").unwrap_or_default();
    let conn = connect()?;
    let article = articles::table.find(id).first::<Article>(&conn)?;
    res.render(Json(row));
    Ok(())
}

Sqlx

main.rs
Cargo.toml
use std::sync::OnceLock;

use salvo::prelude::*;
use serde::Serialize;
use sqlx::{FromRow, PgPool};

// Global PostgreSQL connection pool instance
static POSTGRES: OnceLock<PgPool> = OnceLock::new();

// Helper function to get the PostgreSQL connection pool
#[inline]
pub fn get_postgres() -> &'static PgPool {
    POSTGRES.get().unwrap()
}

// User model representing the database table structure
// Implements FromRow for SQL query results and Serialize for JSON responses
#[derive(FromRow, Serialize, Debug)]
pub struct User {
    pub id: i64,
    pub username: String,
    pub password: String,
}

// Handler for retrieving a user by ID from the database
#[handler]
pub async fn get_user(req: &mut Request, res: &mut Response) {
    // Extract user ID from query parameters
    let uid = req.query::<i64>("uid").unwrap();
    // Execute SQL query to fetch user by ID
    let data = sqlx::query_as::<_, User>("select * from users where id = $1")
        .bind(uid)
        .fetch_one(get_postgres())
        .await
        .unwrap();
    // Return user data as JSON response
    res.render(serde_json::to_string(&data).unwrap());
}

#[tokio::main]
async fn main() {
    // Initialize logging system
    tracing_subscriber::fmt().init();

    // Configure PostgreSQL connection
    let postgres_uri = "postgres://postgres:password@localhost/test";
    // Create and initialize connection pool
    let pool = PgPool::connect(postgres_uri).await.unwrap();
    // Store pool in global state
    POSTGRES.set(pool).unwrap();

    // Configure router with user endpoint:
    // - GET /users?uid={id} : Get user by ID
    let router = Router::with_path("users").get(get_user);

    // Start server on port 8698
    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}

rbatis

main.rs
Cargo.toml
#[macro_use]
extern crate rbatis;
extern crate rbdc;

use std::sync::LazyLock;

use rbatis::RBatis;
use rbdc_mysql::driver::MysqlDriver;
use salvo::prelude::*;
use serde::{Deserialize, Serialize};

// Global RBatis instance for database operations
pub static RB: LazyLock<RBatis> = LazyLock::new(RBatis::new);

// User model representing the database table structure
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct User {
    pub id: i64,
    pub username: String,
    pub password: String,
}

// Implement select query for User model
// Generates SQL: SELECT * FROM user WHERE id = #{id} LIMIT 1
impl_select!(User{select_by_id(id:String) -> Option => "`where id = #{id} limit 1`"});

// Handler for retrieving a user by ID from the database
#[handler]
pub async fn get_user(req: &mut Request, res: &mut Response) {
    // Extract user ID from query parameters
    let uid = req.query::<i64>("uid").unwrap();
    // Execute select query and get user data
    let data = User::select_by_id(&*RB, uid.to_string()).await.unwrap();
    println!("{data:?}");
    // Return user data as JSON response
    res.render(serde_json::to_string(&data).unwrap());
}

#[tokio::main]
async fn main() {
    // Initialize logging system
    tracing_subscriber::fmt().init();

    // Configure MySQL connection
    let mysql_uri = "mysql://root:123456@localhost/test";
    // Initialize RBatis with MySQL driver and connection URI
    RB.init(MysqlDriver {}, mysql_uri).unwrap();

    // Configure router with user endpoint:
    // - GET /users?uid={id} : Get user by ID
    let router = Router::with_path("users").get(get_user);

    // Start server on port 8698
    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}

SeaORM

SeaORM é um ORM assíncrono e dinâmico que oferece suporte robusto a bancos de dados relacionais, incluindo relacionamentos entre entidades, um sistema de migração e um construtor de consultas abrangente e type-safe. É adequado para projetos de médio a grande porte que necessitam de um ORM completo.

Tokio ORM (Toasty)

Toasty é um ORM desenvolvido pela equipe do Tokio, atualmente em desenvolvimento ativo. Foca em fornecer uma solução ORM fortemente integrada ao ecossistema Tokio. Pode ser adequado para projetos que dependem do Tokio e estão abertos a adotar tecnologias emergentes.

SurrealDB Rust SDK

O SDK Rust do SurrealDB fornece conectividade a este banco de dados multi-modelo, tornando-o adequado para aplicações que precisam lidar com dados de grafos, documentos e relacionais. É uma excelente escolha para projetos que exigem modelos de dados flexíveis.