14个版本
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日 |
#182 在 数据库接口
147 每月下载量
用于 2 crates
285KB
6.5K SLoC
Butane
一个专注于简洁性和Rust编写而非SQL的实验性Rust ORM
Butane采用面向对象的方法进行数据库操作。它可以被视为一个对象持久化系统,而不仅仅是一个ORM -- 事实是它由SQL数据库支持,对API消费者来说主要是实现细节。
功能
- 使用类似Rust语法的关联查询(通过
proc-macro
) - 自动迁移,无需编写SQL(尽管必要时可以手动调整生成的SQL)
- 能够在Rust代码中嵌入迁移(以便库可以轻松捆绑其迁移)
- SQLite和PostgreSQL后端
- 无论数据库后端如何,都可以编写全部或几乎全部相同的代码
入门
模型,使用结构体属性声明定义数据库模式。例如,一个博客的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>,
}
一个对象是模型的实例。对象创建的方式与普通的结构体实例一样,但必须保存才能持久化。
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
crate)。fake
:支持fake
crate的伪造数据生成。json
:支持将结构体存储为JSON,包括使用PostgreSQL的JSONB
字段类型。log
:将某些警告记录到log
crate的包装器(目标 "butane")。pg
:使用postgres
crate支持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 的任何贡献都应双许可,没有附加条款或条件。
依赖关系
~4–22MB
~320K SLoC