使用Rust和Diesel ORM创建SQLite CRUD应用

说明:

plaintext 复制代码
cargo install diesel_cli --no-default-features --features "sqlite-bundled"

新建项目

plaintext 复制代码
cargo new diesel_sqlite
cd .\diesel_sqlite\

打开"Cargo.toml",修改为

toml 复制代码
[package]
name = "diesel_sqlite"
version = "0.1.0"
edition = "2021"

[dependencies]
diesel = { version = "2.1.6", features = ["sqlite", "r2d2"] }
dotenv = "0.15.0"
rusqlite = { version = "0.31.0", features = ["bundled"] }

新建".env"文件

plaintext 复制代码
DATABASE_URL=crud.db
plaintext 复制代码
PS > diesel setup
Creating migrations directory at: C:\Users\sywq6\Downloads\diesel_sqlite\diesel_sqlite\migrations
Creating database: crud.db

此时项目文件包括如下:

plaintext 复制代码
│  .env
│  .gitignore
│  Cargo.toml
│  crud.db
│  diesel.toml
│  
├─migrations
│      .keep
│  
└─src
        main.rs
plaintext 复制代码
PS > diesel migration generate create_users
Creating migrations\2024-05-23-142433_create_users\up.sql
Creating migrations\2024-05-23-142433_create_users\down.sql

这条命令生成了用于创建和删除users表的迁移文件。此时项目文件包括如下(新增down.sql和up.sql):

plaintext 复制代码
│  .env
│  .gitignore
│  Cargo.toml
│  crud.db
│  diesel.toml
│  
├─migrations
│  │  .keep
│  │  
│  └─2024-05-23-142433_create_users
│          down.sql
│          up.sql
│      
└─src
        main.rs

修改"up.sql"文件

sql 复制代码
-- Your SQL goes here
CREATE TABLE "users" (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    address TEXT NOT NULL,
    date_created TEXT NOT NULL
);

INSERT INTO
    "users"(name, address, date_created)
VALUES
    ("Ian", "11 Apple Street", "Today");

修改"down.sql"文件

sql 复制代码
-- This file should undo anything in `up.sql`
DROP TABLE users;
sql 复制代码
PS > diesel migration run
Running migration 2024-05-23-142433_create_users

此时项目文件包括如下(新增schema.rs):

sql 复制代码
│  .env
│  .gitignore
│  Cargo.toml
│  crud.db
│  diesel.toml
│  
├─migrations
│  │  .keep
│  │  
│  └─2024-05-23-142433_create_users
│          down.sql
│          up.sql
│      
└─src
        main.rs
        schema.rs

打开schema.rs

rust 复制代码
// @generated automatically by Diesel CLI.

diesel::table! {
    users (id) {
        id -> Nullable<Integer>,
        name -> Text,
        address -> Text,
        date_created -> Text,
    }
}

新建"src/models.rs"文件,这个文件定义了User结构体,用于查询结果的映射。

rust 复制代码
use diesel::{Queryable, Insertable};
use crate::schema::users;

#[derive(Debug, Queryable, Selectable)]
pub struct User {
    pub id: Option<i32>,
    pub name: String,
    pub address: String,
    pub date_created: String,
}

#[derive(Debug, Insertable)]
#[table_name = "users"]
pub struct NewUser<'a> {
    pub name: &'a str,
    pub address: &'a str,
    pub date_created: &'a str,
}

修改"src/main.rs"文件

rust 复制代码
#[macro_use]
extern crate diesel;

mod schema;
mod models;

use diesel::r2d2::{self, ConnectionManager};
use diesel::prelude::*;
use diesel::SqliteConnection;
use dotenv::dotenv;
use std::env;
use crate::schema::users::dsl::*;
use crate::models::User;
use crate::models::NewUser;
use diesel::insert_into;
use std::error::Error;

pub type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>;

fn insert_user(pool: &Pool, new_user: NewUser) -> Result<usize, Box<dyn Error>> {
    let mut db_connection = pool.get()?;
    insert_into(users).values(&new_user).execute(&mut db_connection).map_err(|e| e.into())
}

fn delete_user_by_name(pool: &Pool, user_name: &str) -> Result<usize, Box<dyn Error>> {
    let mut db_connection = pool.get()?;
    diesel::delete(users.filter(name.eq(user_name)))
        .execute(&mut db_connection)
        .map_err(|e| e.into())
}

fn main() {
    dotenv().ok();

    // 从环境变量读取数据库 URL
    let database_url = env::var("DATABASE_URL").unwrap_or_else(|_| {
        eprintln!("DATABASE_URL not found");
        std::process::exit(1);
    });
  
    // 创建数据库连接池
    let database_pool = Pool::builder()
        .build(ConnectionManager::new(database_url))
        .expect("Failed to create pool.");
  

    // 获取一个数据库连接
    let mut db_connection = database_pool.get().expect("Failed to get a connection from the pool.");

    // 插入新用户数据
    let new_user = NewUser {
        name: "Alice",
        address: "22 Orange Avenue",
        date_created: "Today",
    };

    match insert_user(&database_pool, new_user) {
        Ok(_) => println!("New user inserted successfully"),
        Err(err) => eprintln!("Error inserting new user: {}", err),
    }

    // 查询所有用户
    match users.load::<User>(&mut db_connection) {
        Ok(results) => {
            println!("Displaying {} users", results.len());
            for user in results {
                match user.id {
                    Some(user_id) => println!("ID: {}", user_id),  // 使用新的变量名称
                    None => println!("ID: None"),
                }
                println!("Name: {}", user.name);
                println!("Address: {}", user.address);
                println!("Date Created: {}", user.date_created);
                println!("----------\n");
            }
        },
        Err(err) => {
            eprintln!("Error loading users: {}", err);
        },
    }
    // 删除用户
    let user_name_to_delete = "Alice";
    match delete_user_by_name(&database_pool, user_name_to_delete) {
        Ok(count) => println!("Deleted {} users with name '{}'", count, user_name_to_delete),
        Err(err) => eprintln!("Error deleting user: {}", err),
    }
    // 再次查询所有用户
    match users.load::<User>(&mut db_connection) {
        Ok(results) => {
            println!("Displaying {} users", results.len());
            for user in results {
                match user.id {
                    Some(user_id) => println!("ID: {}", user_id),  // 使用新的变量名称
                    None => println!("ID: None"),
                }
                println!("Name: {}", user.name);
                println!("Address: {}", user.address);
                println!("Date Created: {}", user.date_created);
                println!("----------\n");
            }
        },
        Err(err) => {
            eprintln!("Error loading users: {}", err);
        },
    }
}

运行代码:

rust 复制代码
PS > cargo run
...
     Running `target\debug\diesel_sqlite.exe`
New user inserted successfully
Displaying 2 users
ID: 1
Name: Ian
Address: 11 Apple Street
Date Created: Today
----------

ID: 4
Name: Alice
Address: 22 Orange Avenue
Date Created: Today
----------

Deleted 1 users with name 'Alice'
Displaying 1 users
ID: 1
Name: Ian
Address: 11 Apple Street
Date Created: Today
----------
相关推荐
sun0077002 小时前
mysql索引底层原理
数据库·mysql
CHANG_THE_WORLD4 小时前
Rustup 安装加速:使用国内镜像源解决下载慢问题
rust·rustup
workflower5 小时前
MDSE和敏捷开发相互矛盾之处:方法论本质的冲突
数据库·软件工程·敏捷流程·极限编程
Tony小周5 小时前
实现一个点击输入框可以弹出的数字软键盘控件 qt 5.12
开发语言·数据库·qt
noravinsc5 小时前
django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
python·django·sqlite
lifallen5 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
TDengine (老段)6 小时前
TDengine 数据库建模最佳实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
Elastic 中国社区官方博客6 小时前
Elasticsearch 字符串包含子字符串:高级查询技巧
大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
Gauss松鼠会6 小时前
GaussDB应用场景全景解析:从金融核心到物联网的分布式数据库实践
数据库·分布式·物联网·金融·database·gaussdb
守城小轩7 小时前
Chromium 136 编译指南 - Android 篇:开发工具安装(三)
android·数据库·redis