#orm #sql

njord_derive

请勿直接使用此crate,它是Njord的内部组件

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日

#266 in #orm


用于 njord

GPL-3.0 许可证

27KB
212

njord

Njord

build crates.io njord: rustc 1.77.1+ njord_derive: rustc 1.77+ discussions

一个轻量级且可扩展的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时遇到麻烦吗?我们想帮忙!

  • 阅读我们文档上的说明。

  • 如果你正在升级,请阅读发布说明以获取升级说明和“新功能和亮点”。

  • 提出问题,我们监视 stackoverflow.com 上标记为Njord的问题。

  • https://github.com/mjovanc/njord/issues上报告Njord的bug。

报告问题

Njord使用GitHub的集成问题跟踪系统来记录bug和功能请求。如果你要提出问题,请遵循以下建议

  • 在提交bug之前,请先在问题跟踪器中搜索,看看是否有人已经报告了该问题。

  • 如果问题尚未存在,请创建一个新的问题。

  • 请在问题报告中提供尽可能多的信息。我们希望了解您使用的Njord版本、操作系统和Rust版本。

  • 如果您需要粘贴代码或包含堆栈跟踪,请使用Markdown。```可以用来在文本前后进行转义。

  • 如果可能的话,尝试创建一个重现问题的测试用例或项目,并将其附加到问题中。

贡献

在贡献之前,请阅读贡献指南,了解如何开始使用Njord以及提交贡献时应包含的内容。

行为准则

任何与Njord在任何空间(包括但不限于本GitHub仓库)互动的人必须遵守我们的行为准则。

贡献者

以下贡献者要么帮助启动了此项目,要么贡献了代码,要么正在积极维护它(包括文档),或者以其他方式成为本项目的杰出贡献者。我们想花点时间来表彰他们。

mjovanc appelskrutt34

许可证

BSD 3-Clause许可证。

依赖项

~23MB
~437K SLoC