4个版本 (破坏性更新)
0.4.0 | 2024年4月7日 |
---|---|
0.3.0 | 2024年3月15日 |
0.2.0 | 2024年3月15日 |
0.1.0 | 2024年3月15日 |
#1783 in 过程宏
在3个crate中使用(通过miniorm)
19KB
248 行
miniorm
简介
miniorm
crate提供在ORM之上非常简单的接口。
sqlx
已经提供了FromRow
trait,可以自动从数据库行转换到对象。然而,没有相应的宏可以将对象转换回行以插入到数据库中。
这就是miniorm
的作用所在。它提供了多个可以自动派生的特质。使用这些特质,miniorm
提供了一种Store
类型,该类型基于标准“CRUD”操作
- (C)创建
- (R)读取
- (U)更新
- (D)删除
目前,miniorm
支持三种最常见的数据库后端
- Sqlite
- MySql
- Postgres
每个后端都应该使用相应的功能标志来启用。
示例
use sqlx::FromRow;
use miniorm::prelude::*;
#[derive(Debug, Clone, Eq, PartialEq, FromRow, Entity)]
struct Todo {
#[column(TEXT NOT NULL)]
description: String,
#[column(BOOLEAN NOT NULL DEFAULT false)]
done: bool,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let db = sqlx::SqlitePool::connect(":memory:").await?;
let store = miniorm::Store::new(db);
let todo = Todo {
description: "checkout miniorm".into(),
done: false,
};
store.recreate_table().await?;
println!("Inserting...");
let todo = store.create(todo).await?;
println!("Retrieveing by id...");
let mut fetched = store.read(todo.id()).await?;
assert_eq!(todo, fetched);
println!("Updating by id...");
fetched.done = true;
let after_update = store.update(fetched).await?;
assert_eq!(after_update.id(), todo.id());
println!("Listing all...");
let all = store.list().await?;
assert_eq!(all.len(), 1);
assert_eq!(&after_update, &all[0]);
println!("Deleting by id...");
store.delete(todo.id()).await?;
println!("Checking delete successful");
assert!(matches!(
store.read(todo.id()).await,
Err(sqlx::Error::RowNotFound)
));
Ok(())
}
此示例需要sqlite和 |
等等,还有更多!
可以将一个 Store
转换为一个 Router
,该 Router 可以安装来通过 REST API 提供这些 CRUD 操作。为此,您的实体类型应该实现来自 Serialize
和 Deserialize
的 serde
这需要 axum
功能标志。
use axum::Router;
use miniorm::prelude::*;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool};
use std::net::SocketAddr;
use tokio::net::TcpListener;
#[derive(Debug, Clone, Eq, PartialEq, FromRow, Entity, Serialize, Deserialize)]
struct Todo {
#[column(TEXT NOT NULL)]
description: String,
#[column(BOOLEAN NOT NULL DEFAULT false)]
done: bool,
}
impl Todo {
pub fn new(description: impl AsRef<str>) -> Self {
let description = description.as_ref().to_string();
let done = false;
Todo { description, done }
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// connect to db
let db = sqlx::SqlitePool::connect(":memory:").await?;
// initialize todo store
let todos = Store::new(db);
todos.recreate_table().await?;
todos.create(Todo::new("do the laundry")).await?;
todos.create(Todo::new("wash the dishes")).await?;
todos.create(Todo::new("go walk the dog")).await?;
todos.create(Todo::new("groceries")).await?;
// create the app
let app = Router::new().nest("/todos", todos.into_axum_router());
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
println!("listening on http://{}", addr);
// serve the app
let listener = TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await?;
Ok(())
}
此示例需要 sqlite 和 axum 功能标志。 |
依赖项
~1–1.6MB
~33K SLoC