首批通过分布式安全可靠测评,为关键业务系统打造
Diesel 连接 OceanBase 数据库示例程序
更新时间:2026-04-09 14:12:04
功能适用性
Diesel 适用于 OceanBase 数据库 MySQL 模式。
本文将介绍如何使用 Rust 的 Diesel ORM 框架连接 OceanBase 数据库,并实现基本的 CRUD 操作。
环境准备
在开始之前,请确保已安装以下工具:
- Rust 1.78 或更高版本
- Cargo (Rust 的包管理器)
- Diesel CLI 工具
- OceanBase 数据库 V4.2.4 及以上版本 (MySQL 模式) 已安装并运行
- MySQL 5.7 客户端开发库
安装 MySQL 5.7 客户端开发库
rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
yum install -y mysql-community-devel
安装 Diesel CLI
# 安装带有 MySQL 支持的 Diesel CLI
cargo install diesel_cli --no-default-features --features mysql
创建新项目
cargo new diesel-oceanbase-demo
cd diesel-oceanbase-demo
添加依赖
编辑 Cargo.toml 文件,添加以下依赖:
[package]
name = "diesel-oceanbase-demo"
version = "0.1.0"
edition = "2024"
[lib]
name = "diesel_oceanbase_demo" # 注意:这里使用下划线而不是连字符
path = "src/lib.rs"
[dependencies]
diesel = { version = "2.1.0", features = ["mysql", "r2d2", "chrono", "serde_json"] }
dotenv = "0.15"
log = "0.4"
pretty_env_logger = "0.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
数据库准备
设置环境变量:
# 在项目根目录创建 .env 文件 echo 'DATABASE_URL=mysql://username:password@localhost:2881/diesel_demo' > .env初始化数据库:
# 创建数据库并设置表结构 diesel setup创建及编写表文件:
diesel migration generate create_users预期输出:
Creating migrations/2025-05-30-042428_create_users/up.sql Creating migrations/2025-05-30-042428_create_users/down.sql编辑生成的迁移文件
migrations/YYYY-MM-DD-HHMMSS_create_users/up.sql:CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL UNIQUE, active BOOLEAN NOT NULL DEFAULT TRUE );编辑
migrations/YYYY-MM-DD-HHMMSS_create_users/down.sql:DROP TABLE users;初始化 `users 表:
diesel migration run创建
src/schema.rs文件,内容如下:diesel::table! { users (id) { id -> Integer, username -> Varchar, email -> Varchar, active -> Bool, } }
定义模型
创建 src/models.rs 文件:
use serde::{Serialize, Deserialize};
use diesel::prelude::*;
#[derive(Queryable, Selectable, Insertable, AsChangeset, Debug, Serialize, Deserialize)]
#[diesel(table_name = crate::schema::users)]
pub struct User {
pub id: i32,
pub username: String,
pub email: String,
pub active: bool,
}
#[derive(Insertable, Debug, Serialize, Deserialize)]
#[diesel(table_name = crate::schema::users)]
pub struct NewUser<'a> {
pub username: &'a str,
pub email: &'a str,
pub active: bool,
}
#[derive(AsChangeset, Debug, Serialize, Deserialize)]
#[diesel(table_name = crate::schema::users)]
pub struct UpdateUser<'a> {
pub username: Option<&'a str>,
pub email: Option<&'a str>,
pub active: Option<bool>,
}
数据库连接池
创建 src/db.rs 文件:
use diesel::mysql::MysqlConnection;
use diesel::r2d2::{self, ConnectionManager};
use std::env;
pub type Pool = r2d2::Pool<ConnectionManager<MysqlConnection>>;
pub fn init_pool() -> Pool {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let manager = ConnectionManager::<MysqlConnection>::new(database_url);
r2d2::Pool::builder()
.build(manager)
.expect("Failed to create pool")
}
在 src/lib.rs 中导出数据库模块:
pub mod models;
pub mod schema;
pub mod db;
// 重新导出常用类型
pub use db::{init_pool, Pool};
pub use models::{User, NewUser, UpdateUser};
实现数据访问层
创建 src/repositories/user_repository.rs 文件:
use diesel::prelude::*;
use diesel::result::Error;
use crate::models::{User, NewUser, UpdateUser};
use crate::schema::users;
pub struct UserRepository;
impl UserRepository {
pub fn create(conn: &mut MysqlConnection, new_user: NewUser) -> Result<User, Error> {
diesel::insert_into(users::table)
.values(&new_user)
.execute(conn)?;
users::table
.order(users::id.desc())
.first(conn)
}
pub fn find(conn: &mut MysqlConnection, user_id: i32) -> Result<User, Error> {
users::table.find(user_id).first(conn)
}
pub fn update(conn: &mut MysqlConnection, user_id: i32, update_user: UpdateUser) -> Result<User, Error> {
diesel::update(users::table.find(user_id))
.set(&update_user)
.execute(conn)?;
Self::find(conn, user_id)
}
pub fn delete(conn: &mut MysqlConnection, user_id: i32) -> Result<usize, Error> {
diesel::delete(users::table.find(user_id))
.execute(conn)
}
pub fn find_all(conn: &mut MysqlConnection) -> Result<Vec<User>, Error> {
users::table.load(conn)
}
}
创建模块文件
创建
src/repositories/mod.rs文件:pub mod user_repository;更新
src/main.rs文件:mod models; mod schema; mod db; mod repositories; use dotenv::dotenv; use log::info; use crate::models::{NewUser, UpdateUser}; use crate::repositories::user_repository::UserRepository; use crate::db::{init_pool}; fn main() -> Result<(), Box<dyn std::error::Error>> { dotenv().ok(); pretty_env_logger::init(); let pool = init_pool(); let mut conn = pool.get()?; // 创建用户 let new_user = NewUser { username: "testuser", email: "test@example.com", active: true, }; let created_user = UserRepository::create(&mut conn, new_user)?; info!("Created user: {:?}", created_user); // 查询用户 let user = UserRepository::find(&mut conn, created_user.id)?; info!("Found user: {:?}", user); // 更新用户 let update_data = UpdateUser { username: Some("updated_user"), email: Some("updated@example.com"), active: Some(false), }; let updated_user = UserRepository::update(&mut conn, user.id, update_data)?; info!("Updated user: {:?}", updated_user); // 查询所有用户 let all_users = UserRepository::find_all(&mut conn)?; info!("All users: {:?}", all_users); // 删除用户 let count = UserRepository::delete(&mut conn, updated_user.id)?; info!("Deleted {} user(s)", count); Ok(()) }
运行程序
确保 OceanBase 数据库已启动并运行
确保
.env文件已正确配置数据库连接信息运行程序:
RUST_LOG=info cargo run
代码说明
项目结构
db.rs: 数据库连接池配置models/: 数据模型定义repositories/: 数据访问层migrations/: 数据库迁移文件schema.rs: 自动生成的数据库模式
主要组件
- 使用
r2d2管理数据库连接池 - 通过
diesel提供类型安全的查询构建器 - 使用
dotenv管理环境变量 - 使用
log和pretty_env_logger进行日志记录
- 使用
错误处理
- 使用 Rust 的
Result类型进行错误处理 - 提供详细的错误信息和日志
- 使用
?操作符简化错误传播
- 使用 Rust 的
最佳实践
- 分离数据访问逻辑和业务逻辑
- 使用事务确保数据一致性
- 实现适当的错误处理和日志记录
- 使用环境变量管理敏感信息