在Linux环境下用Rust操作数据库,是很多后端开发者绕不开的实战场景。这篇文章会带你从零开始,走完环境准备、库选型、同步/异步操作、ORM使用,再到最佳实践和常见坑的完整流程。顺便说一句,文中所有代码都在Ubuntu 22.04上验证过,但其他发行版也基本通用。

Rust语言在Linux下的数据库操作指南

一、环境准备

1. Rust工具链安装

在Ubuntu或Debian这类Linux发行版上,安装Rust工具链(包含rustc编译器、cargo包管理器)以及必要的编译依赖,只需几条命令:

sudo apt update && sudo apt install -y build-essential curl git
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

验证安装是否成功:

rustc --version   # 查看Rust编译器版本
cargo --version   # 查看包管理器版本

2. 数据库安装(以PostgreSQL为例)

sudo apt install -y postgresql postgresql-contrib   # 安装PostgreSQL及扩展
sudo -u postgres createuser --interactive           # 交互式创建数据库用户(需输入用户名/密码)
sudo -u postgres createdb testdb                    # 为用户创建数据库

如果选用SQLite这种嵌入式数据库,则无需额外安装服务,后面直接用Rust库操作即可,非常方便。

二、常用数据库操作库选择

Rust生态里成熟的数据库库不少,怎么选?看你的场景:

简单说,追求轻量选rusqlite,要异步和高性能选sqlxtokio-postgres,喜欢ORM风格选Diesel

三、同步数据库操作示例(以SQLite为例)

1. 添加依赖

在项目根目录的Cargo.toml中添加rusqlite(支持SQLite)和可选的serde(用于数据序列化):

[dependencies]
rusqlite = { version = "0.26", features = ["bundled"] }   # bundled 包含SQLite源码,无需系统安装
serde = { version = "1.0", features = ["derive"] }       # 可选,用于结构体序列化

2. 基础CRUD操作

use rusqlite::{params, Connection, Result};
use serde::{Serialize, Deserialize};

// 定义用户结构体(可选,用于数据映射)
#[derive(Debug, Serialize, Deserialize)]
struct User {
    id: i32,
    name: String,
    age: i32,
}

fn main() -> Result<()> {
    // 1. 连接数据库(若文件不存在则自动创建)
    let conn = Connection::open("test.db")?;

    // 2. 创建表(IF NOT EXISTS避免重复创建)
    conn.execute(
        "CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            age INTEGER
        )",
        [],
    )?;

    // 3. 插入数据(参数化查询,防止SQL注入)
    conn.execute(
        "INSERT INTO users (name, age) VALUES (?1, ?2)",
        params![ "Alice", 30 ],
    )?;

    // 4. 查询数据(使用query_map映射到结构体)
    let mut stmt = conn.prepare("SELECT id, name, age FROM users")?;
    let user_iter = stmt.query_map([], |row| {
        Ok(User {
            id: row.get(0)?,
            name: row.get(1)?,
            age: row.get(2)?,
        })
    })?;

    for user in user_iter {
        println!("User: {:?}", user?);  // 输出:User { id: 1, name: "Alice", age: 30 }
    }

    Ok(())
}

这里有几个关键点值得注意:

四、异步数据库操作示例(以PostgreSQL为例)

1. 添加依赖

Cargo.toml中添加tokio(异步运行时)和tokio-postgres(PostgreSQL客户端):

[dependencies]
tokio = { version = "1.0", features = ["full"] }   # 异步运行时
tokio-postgres = "0.7"                              # PostgreSQL异步客户端

2. 异步CRUD操作

use tokio_postgres::{NoTls, Error};

#[tokio::main]   // 标记异步主函数
async fn main() -> Result<(), Error> {
    // 1. 连接数据库(异步)
    let (client, connection) = tokio_postgres::connect(
        "host=localhost user=postgres dbname=testdb",   // 连接字符串
        NoTls,                                           // 无TLS加密(生产环境建议启用)
    ).await?;

    // 2. 后台运行连接任务(处理连接错误)
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("Connection error: {}", e);
        }
    });

    // 3. 执行查询(异步)
    let rows = client
        .query("SELECT id, name, age FROM users", &[])
        .await?;

    // 4. 处理结果
    for row in rows {
        let id: i32 = row.get(0);
        let name: String = row.get(1);
        let age: i32 = row.get(2);
        println!("ID: {}, Name: {}, Age: {}", id, name, age);
    }

    Ok(())
}

几个要点:

五、ORM框架使用示例(以Diesel为例)

1. 添加依赖

Cargo.toml中添加diesel(支持PostgreSQL/MySQL/SQLite)和dotenv(环境变量管理):

[dependencies]
diesel = { version = "1.4", features = ["postgres"] }   # 替换为mysql或sqlite适配对应数据库
dotenv = "0.15"                                         # 管理环境变量

2. 配置数据库连接

在项目根目录创建.env文件:

DATABASE_URL=postgres://postgres:your_password@localhost/testdb

3. 定义Schema和模型

运行diesel setup初始化数据库迁移目录,然后创建迁移:

diesel migration generate create_users

编辑迁移文件(migrations/xxxx_create_users/up.sql):

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    age INTEGER
);

运行迁移:

diesel migration run

4. 基础操作

#[macro_use] extern crate diesel;
use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

// 定义模型
#[derive(Queryable, Insertable)]
#[table_name = "users"]
struct User {
    name: String,
    age: i32,
}

fn main() {
    // 加载环境变量
    dotenv().ok();

    // 建立数据库连接
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let connection = PgConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url));

    // 插入数据
    let new_user = User { name: "Bob".to_string(), age: 25 };
    diesel::insert_into(users::table)
        .values(&new_user)
        .execute(&connection)
        .expect("Error sa ving new user");

    // 查询数据
    let results = users::table
        .filter(users::name.like("%B%"))
        .limit(5)
        .load::(&connection)
        .expect("Error loading users");

    println!("Found {} users", results.len());
    for user in results {
        println!("Name: {}, Age: {}", user.name, user.age);
    }
}

Diesel的亮点:

六、开发最佳实践

1. 安全策略

2. 性能优化

七、常见问题解决

本文转载于:https://www.yisu.com/ask/32977861.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。