Rust数据库操作库serde_rusqlite的使用:支持SQLite与Serde的高效序列化与反序列化
Rust数据库操作库serde_rusqlite的使用:支持SQLite与Serde的高效序列化与反序列化
简介
serde_rusqlite是一个提供便捷函数来桥接serde和rusqlite的库。它允许你将rusqlite::Row反序列化为serde::Deserialize类型,并将实现serde::Serialize的类型序列化为rusqlite期望的绑定查询参数(位置参数或命名参数)。
安装
在项目目录中运行以下Cargo命令:
cargo add serde_rusqlite
或者在Cargo.toml中添加:
[dependencies]
serde_rusqlite = "0.40.0"
特性
- 命名绑定参数只支持从struct和map序列化
- 位置绑定参数只支持从tuple、sequence和非可迭代的原始类型序列化
- SQLite支持5种类型:NULL、INTEGER、REAL、TEXT和BLOB
- 特殊类型处理:
- u64如果无法表示为i64会失败
- 简单enum会序列化为字符串
- bool序列化为INTEGER 0或1
- f64和f32的NaN值序列化为NULL
- serde_bytes::Bytes和serde_bytes::ByteBuf作为处理BLOB的优化方式
- unit序列化为NULL
- 只有[u8]序列会使用BLOB数据库类型
- unit_struct序列化为struct名称作为TEXT
示例代码
use serde_derive::{Deserialize, Serialize};
use serde_rusqlite::*;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Example {
id: i64,
name: String,
}
fn main() -> rusqlite::Result<()> {
// 创建内存数据库和表
let connection = rusqlite::Connection::open_in_memory()?;
connection.execute("CREATE TABLE example (id INT, name TEXT)", []).unwrap();
// 使用结构体生成命名绑定查询参数
let row1 = Example { id: 1, name: "first name".into() };
connection.execute(
"INSERT INTO example (id, name) VALUES (:id, :name)",
to_params_named(&row1).unwrap().to_slice().as_slice()
)?;
// 使用元组生成位置绑定查询参数
let row2 = (2, "second name");
connection.execute(
"INSERT INTO example (id, name) VALUES (?, ?)",
to_params(&row2).unwrap()
)?;
// 使用query()和from_rows()反序列化 - 最高效的方式
let mut statement = connection.prepare("SELECT * FROM example")?;
let mut res = from_rows::<Example>(statement.query([])?);
// 获取第一行数据
if let Some(row) = res.next() {
println!("First row: {:?}", row?);
}
Ok(())
}
完整示例
use serde_derive::{Deserialize, Serialize};
use serde_rusqlite::*;
use rusqlite::{params, Connection};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct User {
id: i32,
name: String,
email: String,
active: bool,
}
fn main() -> rusqlite::Result<()> {
// 创建数据库连接
let conn = Connection::open_in_memory()?;
// 创建用户表
conn.execute(
"CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
active INTEGER
)",
[],
)?;
// 插入用户数据
let new_user = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
active: true,
};
// 使用命名参数插入
conn.execute(
"INSERT INTO users (id, name, email, active) VALUES (:id, :name, :email, :active)",
to_params_named(&new_user).unwrap().to_slice().as_slice(),
)?;
// 查询所有用户
let mut stmt = conn.prepare("SELECT id, name, email, active FROM users")?;
let user_iter = from_rows::<User>(stmt.query([])?);
for user in user_iter {
println!("Found user: {:?}", user?);
}
// 更新用户数据
let updated_user = User {
id: 1,
name: "Alice Smith".to_string(),
email: "alice.smith@example.com".to_string(),
active: false,
};
conn.execute(
"UPDATE users SET name = :name, email = :email, active = :active WHERE id = :id",
to_params_named(&updated_user).unwrap().to_slice().as_slice(),
)?;
Ok(())
}
许可证
MIT OR Apache-2.0
1 回复
Rust数据库操作库serde_rusqlite的使用指南
serde_rusqlite
是一个结合了SQLite数据库操作和Serde序列化的Rust库,它允许你在SQLite数据库和Rust数据结构之间进行高效的序列化和反序列化操作。
主要特性
- 无缝集成SQLite和Serde
- 支持自定义类型序列化
- 提供便捷的查询和插入接口
- 类型安全的数据库操作
基本使用方法
添加依赖
首先在Cargo.toml
中添加依赖:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
rusqlite = "0.29.0"
serde_rusqlite = "0.5.0"
定义可序列化的结构体
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct User {
id: i32,
name: String,
email: String,
age: Option<u32>,
}
基本数据库操作示例
use rusqlite::{Connection, params};
use serde_rusqlite::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建或打开数据库连接
let conn = Connection::open_in_memory()?;
// 创建表
conn.execute(
"CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER
)",
[],
)?;
// 插入数据
let user = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
age: Some(30),
};
conn.execute(
"INSERT INTO users (id, name, email, age) VALUES (?1, ?2, ?3, ?4)",
params![user.id, user.name, user.email, user.age],
)?;
// 查询数据 - 使用serde_rusqlite的便捷方法
let mut stmt = conn.prepare("SELECT id, name, email, age FROM users")?;
let users: Vec<User] = from_rows(stmt.query([])?).collect::<Result<_, _>>()?;
println!("Users: {:?}", users);
Ok(())
}
高级用法
使用to_params_named
进行命名参数绑定
let user = User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
age: None,
};
let named_params = to_params_named(&user).unwrap();
conn.execute(
"INSERT INTO users (id, name, email, age) VALUES (:id, :name, :email, :age)",
&named_params,
)?;
处理JSON字段
#[derive(Serialize, Deserialize, Debug)]
struct UserProfile {
preferences: serde_json::Value,
metadata: Option<serde_json::Value>,
}
// 创建支持JSON字段的表
conn.execute(
"CREATE TABLE user_profiles (
user_id INTEGER PRIMARY KEY,
preferences TEXT NOT NULL,
metadata TEXT
)",
[],
)?;
let profile = UserProfile {
preferences: serde_json::json!({
"theme": "dark",
"notifications": true
}),
metadata: Some(serde_json::json!({
"created_at": "2023-01-01",
"source": "web"
})),
};
// 插入JSON数据
conn.execute(
"INSERT INTO user_profiles (user_id, preferences, metadata) VALUES (?1, ?2, ?3)",
params![1, serde_json::to_string(&profile.preferences)?,
profile.metadata.as_ref().map(|m| serde_json::to_string(m)).transpose()?],
)?;
// 查询并反序列化JSON数据
let mut stmt = conn.prepare("SELECT preferences, metadata FROM user_profiles WHERE user_id = ?")?;
let row = stmt.query_row([1], |row| {
let prefs: String = row.get(0)?;
let meta: Option<String> = row.get(1)?;
Ok((prefs, meta))
})?;
let (prefs_str, meta_str) = row;
let prefs: serde_json::Value = serde_json::from_str(&prefs_str)?;
let meta: Option<serde_json::Value> = meta_str.map(|s| serde_json::from_str(&s)).transpose()?;
println!("Preferences: {:?}", prefs);
println!("Metadata: {:?}", meta);
事务处理示例
fn create_user_with_profile(conn: &Connection, user: User, profile: UserProfile) -> Result<(), Box<dyn std::error::Error>> {
let tx = conn.transaction()?;
// 插入用户
tx.execute(
"INSERT INTO users (id, name, email, age) VALUES (?1, ?2, ?3, ?4)",
params![user.id, user.name, user.email, user.age],
)?;
// 插入用户资料
tx.execute(
"INSERT INTO user_profiles (user_id, preferences, metadata) VALUES (?1, ?2, ?3)",
params![
user.id,
serde_json::to_string(&profile.preferences)?,
profile.metadata.as_ref().map(|m| serde_json::to_string(m)).transpose()?
],
)?;
tx.commit()?;
Ok(())
}
性能提示
- 对于批量插入,考虑使用事务
- 预编译常用查询语句
- 对于大型JSON字段,考虑直接使用SQLite的JSON扩展功能
serde_rusqlite
通过结合SQLite的高效存储和Serde的强大序列化能力,为Rust开发者提供了便捷的数据库操作体验。
完整示例代码
下面是一个完整的serde_rusqlite使用示例,包含了基本CRUD操作、事务处理和JSON字段处理:
use rusqlite::{Connection, params};
use serde::{Deserialize, Serialize};
use serde_rusqlite::*;
use serde_json::{json, Value};
#[derive(Serialize, Deserialize, Debug)]
struct User {
id: i32,
name: String,
email: String,
age: Option<u32>,
}
#[derive(Serialize, Deserialize, Debug)]
struct UserProfile {
preferences: Value,
metadata: Option<Value>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建内存数据库连接
let conn = Connection::open_in_memory()?;
// 创建用户表
conn.execute(
"CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER
)",
[],
)?;
// 创建用户资料表
conn.execute(
"CREATE TABLE user_profiles (
user_id INTEGER PRIMARY KEY,
preferences TEXT NOT NULL,
metadata TEXT
)",
[],
)?;
// 示例1: 基本CRUD操作
let user = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
age: Some(30),
};
// 插入用户
conn.execute(
"INSERT INTO users (id, name, email, age) VALUES (?1, ?2, ?3, ?4)",
params![user.id, user.name, user.email, user.age],
)?;
// 查询用户
let mut stmt = conn.prepare("SELECT id, name, email, age FROM users")?;
let users: Vec<User> = from_rows(stmt.query([])?).collect::<Result<_, _>>()?;
println!("All users: {:?}", users);
// 示例2: 使用事务处理
let new_user = User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
age: None,
};
let profile = UserProfile {
preferences: json!({
"theme": "light",
"notifications": false
}),
metadata: Some(json!({
"created_at": "2023-01-02",
"source": "mobile"
})),
};
create_user_with_profile(&conn, new_user, profile)?;
println!("User with profile created successfully");
// 示例3: JSON字段查询
let mut stmt = conn.prepare("SELECT preferences, metadata FROM user_profiles WHERE user_id = ?")?;
let row = stmt.query_row([2], |row| {
let prefs: String = row.get(0)?;
let meta: Option<String> = row.get(1)?;
Ok((prefs, meta))
})?;
let (prefs_str, meta_str) = row;
let prefs: Value = serde_json::from_str(&prefs_str)?;
let meta: Option<Value> = meta_str.map(|s| serde_json::from_str(&s)).transpose()?;
println!("User preferences: {:?}", prefs);
println!("User metadata: {:?}", meta);
Ok(())
}
fn create_user_with_profile(conn: &Connection, user: User, profile: UserProfile) -> Result<(), Box<dyn std::error::Error>> {
let tx = conn.transaction()?;
// 插入用户
tx.execute(
"INSERT INTO users (id, name, email, age) VALUES (?1, ?2, ?3, ?4)",
params![user.id, user.name, user.email, user.age],
)?;
// 插入用户资料
tx.execute(
"INSERT INTO user_profiles (user_id, preferences, metadata) VALUES (?1, ?2, ?3)",
params![
user.id,
serde_json::to_string(&profile.preferences)?,
profile.metadata.as_ref().map(|m| serde_json::to_string(m)).transpose()?
],
)?;
tx.commit()?;
Ok(())
}
这个完整示例展示了:
- 如何定义可序列化的结构体
- 基本的数据库CRUD操作
- 使用事务确保数据一致性
- 处理JSON字段的序列化和反序列化
- 使用serde_rusqlite的便捷查询方法
代码中的注释详细解释了每个步骤的作用,帮助你理解如何使用serde_rusqlite进行高效的数据库操作。