13 个不稳定版本
0.7.0 | 2024年7月17日 |
---|---|
0.6.1 | 2023年5月27日 |
0.5.1 | 2022年12月27日 |
0.5.0 | 2022年11月14日 |
0.1.0 | 2020年12月29日 |
#1221 在 数据库接口
每月151 次下载
58KB
812 行
Butane
一个专注于简单性和 Rust 编写而非 SQL 的 Rust 实验性 ORM
Butane 采用面向对象的方法处理数据库操作。它可以被视为一个对象持久化系统,而不仅仅是 ORM — 事实上,它背后是 SQL 数据库,对 API 消费者来说主要是实现细节。
功能
- 使用类似 Rust 语法的关系查询(通过
proc-macro
) - 无需编写 SQL 即可实现自动迁移(尽管必要时可以手动调整生成的 SQL)
- 能够在 Rust 代码中嵌入迁移(以便库可以轻松捆绑其迁移)
- SQLite 和 PostgreSQL 后端
- 无论数据库后端如何,都可以编写完全相同或几乎相同的代码
入门指南
模型,通过 struct 属性声明,定义数据库模式。例如,博客的 Post 模型可能如下所示
#[model]
#[derive(Default)]
struct Post {
id: AutoPk<i32>,
title: String,
body: String,
published: bool,
likes: i32,
tags: Many<Tag>,
blog: ForeignKey<Blog>,
byline: Option<String>,
}
一个 对象 是一个 模型 的实例。对象就像一个正常的 struct 实例一样创建,但必须保存才能持久化。
let mut post = Post::new(blog, title, body);
post.save(conn)?;
只有在保存时,实例的更改才会应用到数据库中
post.published = true;
post.save(conn)?;
使用 query!
宏以符合人体工程学的方式执行查询。
let posts = query!(Post, published == true).limit(5).load(&conn)?;
有关详细教程,请参阅入门指南。
Cargo 功能
Butane 向 Cargo 公开了几个功能。默认情况下,没有启用任何后端:您将需要启用 sqlite
和/或 pg
default
:启用datetime
、json
和uuid
。debug
:用于开发 Butane,消费者不需要启用。datetime
:支持时间戳(使用chrono
包)。fake
:支持fake
包生成假数据。json
:支持将结构体存储为JSON,包括使用PostgreSQL的JSONB
字段类型。log
:将某些警告记录到log
包门面(目标“butane”)。pg
:支持使用postgres
包的PostgreSQL。r2d2
:使用r2d2
支持连接池(见butane::db::ConnectionManager
)。sqlite
:支持使用rusqlite
包的SQLite。sqlite-bundled
:捆绑sqlite而不是使用系统版本。tls
:使用PostgreSQL时支持TLS,使用postgres-native-tls
包。uuid
:支持UUID(使用uuid
包)。
限制
- Butane及其迁移系统特别期望拥有数据库。它可以与也被其他消费者访问的现有数据库一起使用,但这不是设计目标,也没有设施从现有数据库模式推断出butane模型。
- API的人性化优于性能。这并不意味着Butane很慢,而是当在简单直观的API和尽可能小的开销之间做出选择时,API将获胜。
路线图
Butane很年轻。以下功能目前尚未提供,但计划提供
- 外键约束级联设置
- 增量对象保存
ForeignKey
和Many
的逆向引用。- 在迁移中支持字段/列重命名
- 预置/可重用查询
- 基准测试和性能调整
- 虽然未明确计划支持其他数据库(如MySQL或SQL Server),但欢迎贡献。
与Diesel的比较
Butane受到Diesel和Django ORM的启发。如果你在寻找成熟、性能良好且灵活的ORM,请使用Diesel。Butane并不旨在比Diesel更好,但它做出了一些不同的决定,包括
-
更面向对象,以牺牲灵活性为代价。
-
优先考虑自动迁移。
-
Rust代码是真相之源。模式是从Rust代码中模型的定义中理解的,而不是从数据库中推断出来的。
-
查询是通过在
proc-macro
调用内部使用DSL构建的,而不是通过导入DSL方法/名称到当前作用域中。对于Diesel,你可能写出use diesel_demo::schema::posts::dsl::*; let posts = posts.filter(published.eq(true)) .limit(5) .load::<Post>(&conn)?
而对于Butane,你将改写为
let posts = query!(Post, published == true).limit(5).load(&conn)?;
哪种形式更可取主要是一种审美判断。
-
数据库后端之间的差异在很大程度上被隐藏。
-
Diesel在总体上要成熟得多,功能更丰富。
有关详细教程,请参阅入门指南。
许可证
Butane根据你的选择,受MIT许可证或Apache许可证2.0的约束。
除非你明确声明,否则,根据Apache-2.0许可证定义的,你提交的任何有意包含在Butane中的贡献,均应根据上述内容双许可,没有任何附加条款或条件。
依赖关系
~9–24MB
~381K SLoC