Skip to main content

What's new in SeaORM 0.3.0

ยท 4 min read
SeaQL Team

๐ŸŽ‰ We are pleased to release SeaORM 0.3.0 today! Here are some feature highlights ๐ŸŒŸ:

Transactionโ€‹

[#222] Use database transaction to perform atomic operations

Two transaction APIs are provided:

  • closure style. Will be committed on Ok and rollback on Err.

    // <Fn, A, B> -> Result<A, B>
    db.transaction::<_, _, DbErr>(|txn| {
    Box::pin(async move {
    bakery::ActiveModel {
    name: Set("SeaSide Bakery".to_owned()),
    ..Default::default()
    }
    .save(txn)
    .await?;

    bakery::ActiveModel {
    name: Set("Top Bakery".to_owned()),
    ..Default::default()
    }
    .save(txn)
    .await?;

    Ok(())
    })
    })
    .await;
  • RAII style. begin the transaction followed by commit or rollback. If txn goes out of scope, it'd automatically rollback.

    let txn = db.begin().await?;

    // do something with txn

    txn.commit().await?;

Contributed by:

Marco Napetti
Chris Tsang

Streamingโ€‹

[#222] Use async stream on any Select for memory efficiency.

let mut stream = Fruit::find().stream(&db).await?;

while let Some(item) = stream.try_next().await? {
let item: fruit::ActiveModel = item.into();
// do something with item
}

Contributed by:

Marco Napetti

API for custom logic on save & deleteโ€‹

[#210] We redefined the trait methods of ActiveModelBehavior. You can now perform custom validation before and after insert, update, save, delete actions. You can abort an action even after it is done, if you are inside a transaction.

impl ActiveModelBehavior for ActiveModel {
// Override default values
fn new() -> Self {
Self {
serial: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}

// Triggered before insert / update
fn before_save(self, insert: bool) -> Result<Self, DbErr> {
if self.price.as_ref() <= &0.0 {
Err(DbErr::Custom(format!(
"[before_save] Invalid Price, insert: {}",
insert
)))
} else {
Ok(self)
}
}

// Triggered after insert / update
fn after_save(self, insert: bool) -> Result<Self, DbErr> {
Ok(self)
}

// Triggered before delete
fn before_delete(self) -> Result<Self, DbErr> {
Ok(self)
}

// Triggered after delete
fn after_delete(self) -> Result<Self, DbErr> {
Ok(self)
}
}

Contributed by:

Muhannad
Billy Chan

Generate Entity Models That Derive Serialize / Deserializeโ€‹

[#237] You can use sea-orm-cli to generate entity models that also derive serde Serialize / Deserialize traits.

//! SeaORM Entity. Generated by sea-orm-codegen 0.3.0

use sea_orm::entity::prelude:: * ;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "cake")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Text", nullable)]
pub name: Option<String> ,
}

// ...

Contributed by:

Tim Eggert

Introduce DeriveIntoActiveModel macro & IntoActiveValue Traitโ€‹

[#240] introduced a new derive macro DeriveIntoActiveModel for implementing IntoActiveModel on structs. This is useful when creating your own struct with only partial fields of a model, for example as a form submission in a REST API.

IntoActiveValue trait allows converting Option<T> into ActiveValue<T> with the method into_active_value.

// Define regular model as usual
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
pub id: Uuid,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
pub email: String,
pub password: String,
pub full_name: Option<String>,
pub phone: Option<String>,
}

// Create a new struct with some fields omitted
#[derive(DeriveIntoActiveModel)]
pub struct NewUser {
// id, created_at and updated_at are omitted from this struct,
// and will always be `ActiveValue::unset`
pub email: String,
pub password: String,
// Full name is usually optional, but it can be required here
pub full_name: String,
// Option implements `IntoActiveValue`, and when `None` will be `unset`
pub phone: Option<String>,
}

#[derive(DeriveIntoActiveModel)]
pub struct UpdateUser {
// Option<Option<T>> allows for Some(None) to update the column to be NULL
pub phone: Option<Option<String>>,
}

Contributed by:

Ari Seyhun

Communityโ€‹

SeaQL is a community driven project. We welcome you to participate, contribute and together build for Rust's future.

Here is the roadmap for SeaORM 0.4.x.