使用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
----------
相关推荐
建投数据26 分钟前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi1 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀1 小时前
Redis梳理
数据库·redis·缓存
独行soc1 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天2 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺2 小时前
分布式系统架构:服务容错
数据库·架构
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘
White_Mountain4 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
Code apprenticeship4 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站4 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle