Rust Oracle数据库操作宏库oracle_procmacro的使用:简化Oracle数据库交互的proc-macro扩展
Rust Oracle数据库操作宏库oracle_procmacro的使用:简化Oracle数据库交互的proc-macro扩展
oracle_procmacro 是为 oracle crate 定义的过程宏扩展,它提供了以下宏:
RowValue
派生宏
安装
在项目目录中运行以下Cargo命令:
cargo add oracle_procmacro
或者在Cargo.toml中添加:
oracle_procmacro = "0.1.2"
使用示例
以下是一个使用 oracle_procmacro
和 oracle
crate 的完整示例:
use oracle::{Connection, RowValue};
use oracle_procmacro::RowValue;
// 定义一个结构体并派生RowValue
#[derive(Debug, RowValue)]
struct Employee {
emp_id: i32,
emp_name: String,
salary: Option<f64>,
hire_date: oracle::Date,
}
fn main() -> oracle::Result<()> {
// 连接到Oracle数据库
let conn = Connection::connect("username", "password", "//localhost:1521/ORCL")?;
// 创建表
conn.execute(
"CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(100),
salary NUMBER(10,2),
hire_date DATE
)",
&[],
)?;
// 插入数据
let employees = vec![
Employee {
emp_id: 1,
emp_name: "John Doe".to_string(),
salary: Some(50000.0),
hire_date: oracle::Date::from_string("2020-01-15", "YYYY-MM-DD")?,
},
Employee {
emp_id: 2,
emp_name: "Jane Smith".to_string(),
salary: Some(60000.0),
hire_date: oracle::Date::from_string("2019-05-20", "YYYY-MM-DD")?,
},
];
for emp in &employees {
conn.execute(
"INSERT INTO employees (emp_id, emp_name, salary, hire_date) VALUES (:1, :2, :3, :4)",
&[&emp.emp_id, &emp.emp_name, &emp.salary, &emp.hire_date],
)?;
}
// 查询数据并使用RowValue自动转换
let stmt = conn.prepare("SELECT emp_id, emp_name, salary, hire_date FROM employees")?;
let rows = stmt.query(&[])?;
for row_result in rows {
let row = row_result?;
// 自动将行转换为Employee结构体
let emp: Employee = row.to_struct()?;
println!("{:?}", emp);
}
Ok(())
}
完整示例代码
// 引入必要的库和宏
use oracle::{Connection, RowValue};
use oracle_procmacro::RowValue;
// 定义员工结构体并派生RowValue trait
#[derive(Debug, RowValue)]
struct Employee {
emp_id: i32, // 员工ID
emp_name: String, // 员工姓名
salary: Option<f64>, // 工资(可能为NULL)
hire_date: oracle::Date, // 雇佣日期
}
// 主函数返回oracle crate的Result类型
fn main() -> oracle::Result<()> {
// 1. 建立数据库连接
let conn = Connection::connect(
"your_username",
"your_password",
"//localhost:1521/ORCL"
)?;
// 2. 创建员工表
conn.execute(
r#"CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(100) NOT NULL,
salary NUMBER(10,2),
hire_date DATE NOT NULL
)"#,
&[]
)?;
println!("表创建成功");
// 3. 准备员工数据
let employees = vec![
Employee {
emp_id: 101,
emp_name: "张三".to_string(),
salary: Some(8500.50),
hire_date: oracle::Date::from_string("2021-03-15", "YYYY-MM-DD")?,
},
Employee {
emp_id: 102,
emp_name: "李四".to_string(),
salary: None, // 表示NULL值
hire_date: oracle::Date::from_string("2020-11-22", "YYYY-MM-DD")?,
},
];
// 4. 批量插入数据
for emp in &employees {
conn.execute(
r#"INSERT INTO employees
(emp_id, emp_name, salary, hire_date)
VALUES (:1, :2, :3, :4)"#,
&[&emp.emp_id, &emp.emp_name, &emp.salary, &emp.hire_date],
)?;
}
println!("数据插入成功");
// 5. 查询数据并使用RowValue自动转换
println!("\n查询结果:");
let stmt = conn.prepare(
"SELECT emp_id, emp_name, salary, hire_date FROM employees ORDER BY emp_id"
)?;
let rows = stmt.query(&[])?;
// 6. 遍历结果并转换为Employee结构体
for row_result in rows {
let row = row_result?;
let emp: Employee = row.to_struct()?; // 自动转换
println!("{:#?}", emp);
}
// 7. 清理表(演示用)
conn.execute("DROP TABLE employees PURGE", &[])?;
println!("\n表已删除");
Ok(())
}
功能说明
RowValue
派生宏允许将查询结果自动转换为Rust结构体- 支持Oracle的基本数据类型到Rust类型的转换
- 处理NULL值通过Option类型
- 支持日期时间等特殊类型的转换
文档
更多详细用法请参考官方文档。
许可证
该库采用UPL-1.0或Apache-2.0许可证。
1 回复
Rust Oracle数据库操作宏库oracle_procmacro使用指南
简介
oracle_procmacro
是一个简化Rust与Oracle数据库交互的过程宏库,它通过提供声明式宏来减少样板代码,使Oracle数据库操作更加简洁直观。
主要特性
- 自动处理连接池管理
- 简化SQL查询执行
- 类型安全的参数绑定
- 自动结果集映射
- 支持事务操作
安装
在Cargo.toml中添加依赖:
[dependencies]
oracle_procmacro = "0.1"
tokio = { version = "1.0", features = ["full"] }
基本使用方法
1. 建立连接
use oracle_procmacro::oracle_connect;
#[oracle_connect(
url = "oracle://username:password@localhost:1521/ORCLCDB",
pool_size = 5
)]
struct DbConnection;
2. 执行查询
use oracle_procmacro::oracle_query;
#[oracle_query(
sql = "SELECT id, name, salary FROM employees WHERE department = :dept",
fetch = "all"
)]
struct GetEmployeesByDept {
dept: String,
}
3. 使用查询
#[tokio::main]
async fn main() {
let conn = DbConnection::new().await;
let employees = GetEmployeesByDept { dept: "IT".to_string() }
.execute(&conn)
.await
.unwrap();
for emp in employees {
println!("ID: {}, Name: {}, Salary: {}", emp.id, emp.name, emp.salary);
}
}
高级用法
事务支持
use oracle_procmacro::oracle_transaction;
#[oracle_transaction]
async fn update_employee_salary(conn: &DbConnection, emp_id: i32, new_salary: f64) -> Result<(), String> {
#[oracle_query(sql = "UPDATE employees SET salary = :salary WHERE id = :id")]
struct UpdateSalary {
id: i32,
salary: f64,
}
UpdateSalary { id: emp_id, salary: new_salary }
.execute(conn)
.await
.map_err(|e| e.to_string())?;
Ok(())
}
批量操作
use oracle_procmacro::oracle_batch;
#[oracle_batch(
sql = "INSERT INTO employees (id, name, department) VALUES (:id, :name, :dept)",
batch_size = 100
)]
struct BatchInsertEmployee {
id: i32,
name: String,
dept: String,
}
#[tokio::main]
async fn main() {
let conn = DbConnection::new().await;
let employees = vec![
BatchInsertEmployee { id: 1, name: "Alice".to_string(), dept: "IT".to_string() },
BatchInsertEmployee { id: 2, name: "Bob".to_string(), dept: "HR".to_string() },
// ...更多记录
];
BatchInsertEmployee::execute_batch(&conn, employees).await.unwrap();
}
自定义类型映射
use oracle_procmacro::oracle_type_mapping;
#[oracle_type_mapping]
mod custom_types {
pub struct MyCustomType(String);
impl From<oracle::SqlValue> for MyCustomType {
fn from(value: oracle::SqlValue) -> Self {
MyCustomType(value.get_string().unwrap())
}
}
impl Into<oracle::SqlValue> for MyCustomType {
fn into(self) -> oracle::SqlValue {
oracle::SqlValue::String(self.0)
}
}
}
错误处理
所有操作都返回Result
类型,可以方便地进行错误处理:
#[tokio::main]
async fn main() {
let conn = DbConnection::new().await;
let result = GetEmployeesByDept { dept: "IT".to_string() }
.execute(&conn)
.await;
match result {
Ok(employees) => {
// 处理成功结果
},
Err(e) => {
eprintln!("查询失败: {}", e);
// 错误处理逻辑
}
}
}
性能提示
- 连接池大小应根据应用负载调整
- 批量操作比单条操作效率更高
- 复杂查询考虑使用存储过程
完整示例
以下是一个完整的Rust程序示例,展示了如何使用oracle_procmacro库进行Oracle数据库操作:
use oracle_procmacro::{oracle_connect, oracle_query, oracle_batch, oracle_transaction};
// 1. 建立数据库连接
#[oracle_connect(
url = "oracle://username:password@localhost:1521/ORCLCDB",
pool_size = 5
)]
struct DbConnection;
// 2. 定义查询结构体
#[oracle_query(
sql = "SELECT id, name, salary FROM employees WHERE department = :dept",
fetch = "all"
)]
struct GetEmployeesByDept {
dept: String,
}
// 3. 定义批量插入结构体
#[oracle_batch(
sql = "INSERT INTO employees (id, name, department) VALUES (:id, :name, :dept)",
batch_size = 100
)]
struct BatchInsertEmployee {
id: i32,
name: String,
dept: String,
}
// 4. 定义事务操作函数
#[oracle_transaction]
async fn transfer_employee(
conn: &DbConnection,
emp_id: i32,
new_dept: String,
new_salary: f64
) -> Result<(), String> {
#[oracle_query(sql = "UPDATE employees SET department = :dept WHERE id = :id")]
struct UpdateDept {
id: i32,
dept: String,
}
#[oracle_query(sql = "UPDATE employees SET salary = :salary WHERE id = :id")]
struct UpdateSalary {
id: i32,
salary: f64,
}
UpdateDept { id: emp_id, dept: new_dept }
.execute(conn)
.await
.map_err(|e| e.to_string())?;
UpdateSalary { id: emp_id, salary: new_salary }
.execute(conn)
.await
.map_err(|e| e.to_string())?;
Ok(())
}
#[tokio::main]
async fn main() {
// 初始化连接
let conn = DbConnection::new().await;
// 示例1: 查询操作
let it_employees = GetEmployeesByDept { dept: "IT".to_string() }
.execute(&conn)
.await
.unwrap();
println!("IT部门员工:");
for emp in it_employees {
println!("ID: {}, Name: {}, Salary: {}", emp.id, emp.name, emp.salary);
}
// 示例2: 批量插入
let new_employees = vec![
BatchInsertEmployee { id: 101, name: "Charlie".to_string(), dept: "Finance".to_string() },
BatchInsertEmployee { id: 102, name: "David".to_string(), dept: "Marketing".to_string() },
BatchInsertEmployee { id: 103, name: "Eve".to_string(), dept: "Engineering".to_string() },
];
BatchInsertEmployee::execute_batch(&conn, new_employees).await.unwrap();
println!("成功批量插入员工记录");
// 示例3: 事务操作
match transfer_employee(&conn, 101, "Engineering".to_string(), 85000.0).await {
Ok(_) => println!("员工部门转移成功"),
Err(e) => eprintln!("事务失败: {}", e),
}
}
这个完整示例展示了:
- 数据库连接池的建立
- 基本查询操作
- 批量数据插入
- 事务处理
- 错误处理
您可以根据实际需求调整SQL语句和参数,这个宏库可以大大简化Oracle数据库操作代码。