🐚 An async & dynamic ORM for Rust
[](https://crates.io/crates/sea-orm) [](https://docs.rs/sea-orm) [](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml) Built with 🔥 by 🌊🦀🐚SeaORM is a relational ORM to help you build light weight and concurrent web services in Rust.
Async
Relying on SQLx, SeaORM is a new library with async support from day 1.
rust
// execute multiple queries in parallel
let cakes_and_fruits: (Vec<cake::Model>, Vec<fruit::Model>) =
futures::try_join!(Cake::find().all(&db), Fruit::find().all(&db))?;
Dynamic
Built upon SeaQuery, SeaORM allows you to build complex queries without 'fighting the ORM'.
```rust
// build subquery with ease
let cakeswithfilling: Vec
```
Testable
Use mock connections to write unit tests for your logic.
```rust // Setup mock connection let db = MockDatabase::new(DbBackend::Postgres) .appendqueryresults(vec![ vec![ cake::Model { id: 1, name: "New York Cheese".toowned(), }, ], ]) .intoconnection();
// Perform your application logic asserteq!( cake::Entity::find().one(&db).await?, Some(cake::Model { id: 1, name: "New York Cheese".toowned(), }) );
// Compare it against the expected transaction log asserteq!( db.intotransactionlog(), vec![ Transaction::fromsqlandvalues( DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#, vec![1u64.into()] ), ] ); ```
Service Oriented
Quickly build services that join, filter, sort and paginate data in APIs.
```rust
async fn list(
conn: Connection
// Setup paginator
let paginator = Post::find()
.order_by_asc(post::Column::Id)
.paginate(&conn, per_page);
let num_pages = paginator.num_pages().await.unwrap();
// Fetch paginated posts
let posts = paginator
.fetch_page(page - 1)
.await
.expect("could not retrieve posts");
Template::render(
"index",
context! {
page: page,
per_page: per_page,
posts: posts,
num_pages: num_pages,
},
)
} ```
```rust
// find all models
let cakes: Vec
// find and filter
let chocolate: Vec
// find one model
let cheese: Option
// find related models (lazy)
let fruits: Vec
// find related models (eager)
let cakewithfruits: Vec<(cake::Model, Vec
```
```rust let apple = fruit::ActiveModel { name: Set("Apple".to_owned()), ..Default::default() // no need to set primary key };
let pear = fruit::ActiveModel { name: Set("Pear".to_owned()), ..Default::default() };
// insert one let pear = pear.insert(db).await?;
// insert many Fruit::insert_many(vec![apple, pear]).exec(db).await?; ```
```rust use seaorm::seaquery::{Expr, Value};
let pear: Option
pear.name = Set("Sweet pear".to_owned());
// update one let pear: fruit::ActiveModel = pear.update(db).await?;
// update many: UPDATE "fruit" SET "cakeid" = NULL WHERE "fruit"."name" LIKE '%Apple%' Fruit::updatemany() .col_expr(fruit::Column::CakeId, Expr::value(Value::Int(None))) .filter(fruit::Column::Name.contains("Apple")) .exec(db) .await?;
```
```rust let banana = fruit::ActiveModel { id: Unset(None), name: Set("Banana".to_owned()), ..Default::default() };
// create, because primary key id
is Unset
let mut banana = banana.save(db).await?;
banana.name = Set("Banana Mongo".to_owned());
// update, because primary key id
is Set
let banana = banana.save(db).await?;
```
```rust
let orange: Option
// delete one fruit::Entity::delete(orange).exec(db).await?; // or simply orange.delete(db).await?;
// delete many: DELETE FROM "fruit" WHERE "fruit"."name" LIKE 'Orange' fruit::Entity::delete_many() .filter(fruit::Column::Name.contains("Orange")) .exec(db) .await?;
```
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.