Sea-ORM is an async Rust ORM that uses a code-first approach where you define your database schema in Rust structs, then generate migration files and query builders automatically. You start by defining your entity models with the sea_orm::EntityTrait and sea_orm::ActiveModelTrait, then use the generated query builder to perform type-safe database operations.
First, add the dependencies to your Cargo.toml. You need the core library, the runtime (like tokio), and the migration generator.
[dependencies]
sea-orm = { version = "1", features = ["sqlx-postgres", "runtime-tokio-rustls"] }
sea-orm-migration = { version = "1", features = ["sqlx-postgres"] }
Define your entity in src/entity.rs using the derive macros. This single definition generates the migration SQL, the query builder methods, and the active model for inserts/updates.
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub email: String,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
To generate the initial migration, run the CLI tool. This creates a migrations folder with the SQL needed to create the user table based on your Rust struct.
cargo sea-orm-cli generate migration --name init
In your application logic, connect to the database and use the generated Entity to query or insert data. The query builder is fluent and type-safe, preventing SQL injection and compile-time errors.
use sea_orm::{Database, DbConn, EntityTrait, QueryFilter};
#[tokio::main]
async fn main() -> Result<(), sea_orm::DbErr> {
let db = Database::connect("postgres://user:pass@localhost/dbname").await?;
// Insert a new user
let user = user::ActiveModel {
name: Set("Alice".to_owned()),
email: Set("alice@example.com".to_owned()),
..Default::default()
};
let inserted = user.insert(&db).await?;
// Query users by name
let users = User::find()
.filter(user::Column::Name.eq("Alice"))
.all(&db)
.await?;
println!("Found {} users", users.len());
Ok(())
}
Sea-ORM handles the heavy lifting of mapping Rust types to SQL types, managing connections asynchronously, and providing a consistent API across different database backends like PostgreSQL, MySQL, and SQLite.