使用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
----------
相关推荐
月光水岸New1 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6751 小时前
数据库基础1
数据库
我爱松子鱼1 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo2 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser3 小时前
【SQL】多表查询案例
数据库·sql
Galeoto3 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
人间打气筒(Ada)3 小时前
MySQL主从架构
服务器·数据库·mysql
leegong231113 小时前
学习PostgreSQL专家认证
数据库·学习·postgresql
喝醉酒的小白3 小时前
PostgreSQL:更新字段慢
数据库·postgresql
敲敲敲-敲代码3 小时前
【SQL实验】触发器
数据库·笔记·sql