4个版本 (2个破坏性更新)
0.3.0 | 2024年5月8日 |
---|---|
0.2.1 | 2024年3月25日 |
0.2.0 | 2024年3月25日 |
0.1.0 | 2023年10月7日 |
#358 在 数据库接口
72KB
717 行
Njord
一个轻量且可扩展的Rust ORM库。
目录
支持的数据库
数据库 | 支持 | 状态 |
---|---|---|
SQLite | ✅ | 目前支持。 |
PostgreSQL | ❌ | 不支持,帮助我们实现它吗? |
MySQL | ❌ | 不支持,帮助我们实现它吗? |
MariaDB | ❌ | 不支持,帮助我们实现它吗? |
Oracle | ❌ | 不支持,帮助我们实现它吗? |
MSSQL | ❌ | 不支持,帮助我们实现它吗? |
入门指南
初始化新项目
首先我们需要生成我们的项目。
cargo new --bin njord_demo
现在,让我们将Njord添加到我们的依赖项中。我们还将使用一个名为.env的工具来管理我们的环境变量。我们也会将其添加到依赖项中。
[dependencies]
# The core APIs, including the Table trait.
# using #[derive(Table)] to make njord work with structs
# and enums defined in your crate.
njord = { version = "<version>", features = ["sqlite"] }
njord_derive = { version = "<version>" }
添加模式文件
现在,我们需要定义我们的模式文件,它将位于 src/schema.rs
之下。我们将存储基本的结构,这些结构将映射到数据库上。
#[derive(Table)]
#[table_name = "users"]
pub struct User {
id: usize,
username: String,
email: String,
address: String,
}
#[derive(Table)]
#[table_name = "categories"]
pub struct Category {
id: usize,
name: String,
}
#[derive(Table)]
#[table_name = "products"]
pub struct Product {
id: usize,
name: String,
description: String,
price: f64,
stock_quantity: usize,
category: Category, // one-to-one relationship
discount: Option<f64>, // allow for null
}
#[derive(Table)]
#[table_name = "orders"]
pub struct Order {
id: usize,
user: User, // one-to-one relationship
products: Vec<Product>, // one-to-many relationship - populates from based on junction table (gets from macro attribute "table_name" and combines them for example, orders_products)
total_cost: f64,
}
现在我们已经有了这些,我们需要创建SQL以在数据库中设置它并执行它。
-- users table
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
email TEXT NOT NULL,
address TEXT NOT NULL
);
-- products table
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
price REAL NOT NULL,
stock_quantity INTEGER NOT NULL,
category INTEGER REFERENCES categories(id),
discount: REAL NULL
);
-- orders table
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
total_cost REAL NOT NULL
);
-- order_products table
CREATE TABLE order_products (
order_id INTEGER REFERENCES orders(id),
product_id INTEGER REFERENCES products(id),
PRIMARY KEY (order_id, product_id)
);
使用方法
那么我们如何建立连接并实际选择或插入数据库中的数据?让我们看看。注意,这些示例可能已经过时,所以不要将其视为真实信息来源。
SQLite
建立连接
要建立连接,我们首先需要调用 sqlite::open()
函数,并用一个match语句使用它。
let db_name = "njord.db";
let db_path = Path::new(&db_name);
match sqlite::open(db_path) {
Ok(c) => {
println!("Database opened successfully!");
// Additional logic when we are connected.
// We need to open a connection and pass it
// to the corresponding sqlite function.
}
Err(err) => eprintln!("Error opening the database: {}", err),
}
插入数据
let user = User {
username: String::from("john_doe"),
email: String::from("[email protected]"),
address: String::from("123 Main St"),
};
let result = sqlite::insert(c, vec![user]);
assert!(result.is_ok());
生成的SQL
INSERT INTO users (
username,
email,
address
) VALUES (
'john_doe',
'[email protected]',
'123 Main St'
)
更新数据
let columns = vec!["username".to_string(), "address".to_string()];
let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());
let user = User {
username: String::from("john_doe_2"),
email: String::from("[email protected]"),
address: String::from("1234 Main St"),
};
let mut order = HashMap::new();
order.insert(vec!["id".to_string()], "DESC".to_string());
let result = sqlite::update(c, user)
.set(columns)
.where_clause(where_condition)
.order_by(order)
.limit(4)
.offset(0)
.build();
assert!(result.is_ok());
生成的SQL
UPDATE users
SET
username
WHERE
username = 'john_doe'
ORDER BY
id DESC
LIMIT 4
OFFSET 0
删除数据
let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());
let mut order = HashMap::new();
order.insert(vec!["id".to_string()], "DESC".to_string());
let result = sqlite::delete(c)
.from(User::default())
.where_clause(where_condition)
.order_by(order)
.limit(20)
.offset(0)
.build();
assert!(result.is_ok());
生成的SQL
DELETE FROM users
WHERE
username = 'john_doe'
ORDER BY
id DESC
LIMIT 20
OFFSET 0
选择数据
let columns = vec!["id".to_string(), "username".to_string(), "email".to_string(), "address".to_string()];
let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());
let group_by = vec!["username".to_string(), "address".to_string()];
let mut order_by = HashMap::new();
order_by.insert(vec!["id".to_string()], "ASC".to_string());
let having_condition = Condition::Gt("id".to_string(), "1".to_string());
// Build the query
// We need to pass the struct User with the Default trait in .from()
let result: Result<Vec<User>> = sqlite::select(c, columns)
.from(User::default())
.where_clause(where_condition)
.order_by(order_by)
.group_by(group_by)
.having(having_condition)
.build();
match result {
Ok(result) => {
assert_eq!(result.len(), 1);
}
Err(error) => panic!("Failed to SELECT: {:?}", error),
};
生成的SQL
SELECT
id,
username,
email,
address
FROM
users
WHERE
username = 'mjovanc'
GROUP BY
username,
email
HAVING
id > 1
ORDER BY
email DESC
寻求帮助
你在使用Njord时遇到问题吗?我们想要帮助你!
-
阅读我们文档中的说明。
-
如果你正在升级,请阅读发布说明以获取升级说明和“新特性”。
-
在我们的Stack Overflow(https://stackoverflow.com)上提出问题,我们将监控带有Njord标签的问题。
-
在https://github.com/mjovanc/njord/issues上报告Njord的bug。
报告问题
Njord使用GitHub的集成问题跟踪系统来记录bug和功能请求。如果你想提出一个问题,请遵循以下建议
-
在报告bug之前,请搜索问题跟踪器以查看是否有人已经报告了该问题。
-
如果问题尚不存在,则创建一个新的问题。
-
请在问题报告中提供尽可能多的信息。我们想知道您使用的Njord版本、操作系统和Rust版本。
-
如果您需要粘贴代码或包含堆栈跟踪,请使用Markdown。```请将您的文本包围起来。
-
如果可能,尝试创建一个重现问题的测试用例或项目,并将其附加到问题中。
贡献
在贡献之前,请阅读贡献指南,以获取有关如何开始使用Njord以及提交贡献时应包含的内容的有用信息。
行为准则
任何与Njord在任何空间互动的人,包括但不限于这个GitHub仓库,都必须遵守我们的行为准则。
贡献者
以下贡献者要么帮助启动了这个项目,要么贡献了代码,正在积极维护它(包括文档),或者以其他方式成为这个项目的杰出贡献者。我们想花点时间来认可他们。
许可协议
BSD 3-Clause许可证。
依赖关系
~23MB
~444K SLoC