SeaORM

SeaORM is a powerful ORM for building web services in Rust

[![crate](https://img.shields.io/crates/v/sea-orm.svg)](https://crates.io/crates/sea-orm) [![build status](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml/badge.svg)](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml) [![GitHub stars](https://img.shields.io/github/stars/SeaQL/sea-orm.svg?style=social&label=Star&maxAge=1)](https://github.com/SeaQL/sea-orm/stargazers/)
Support us with a ⭐ !
# 🐚 SeaORM [δΈ­ζ–‡ζ–‡ζ‘£](https://github.com/SeaQL/sea-orm/blob/master/README-zh.md) ### Advanced Relations Model complex relationships 1-1, 1-N, M-N, and even self-referential in a high-level, conceptual way. ### Familiar Concepts Inspired by popular ORMs in the Ruby, Python, and Node.js ecosystem, SeaORM offers a developer experience that feels instantly recognizable. ### Feature Rich SeaORM is a batteries-included ORM with filters, pagination, and nested queries to accelerate building REST, GraphQL, and gRPC APIs. ### Production Ready With 250k+ weekly downloads, SeaORM is production-ready, trusted by startups and enterprises worldwide. ## TLS configuration SeaORM's default features do not enable TLS. To select a TLS backend for SQLx, you need to add a SQLx dependency with the desired TLS feature. For example, to use sqlx-postgres with tokio and AWS-LC: ```toml [dependencies] sea-orm = { version = "2", features = ["sqlx-postgres", "runtime-tokio"] } sqlx = { version = "0.9", features = ["tls-rustls-aws-lc-rs"] } ``` When using `sea-orm-cli` as a dependency, its defaults enable `runtime-tokio-native-tls`. To select another TLS backend, you need to disable the default features: ```toml [dependencies] sea-orm-cli = { version = "2", default-features = false, features = [ "codegen", "sqlx-postgres", "runtime-tokio", ] } sqlx = { version = "0.9", features = ["tls-rustls-aws-lc-rs"] } ``` ## Getting Started [![Discord](https://img.shields.io/discord/873880840487206962?label=Discord)](https://discord.com/invite/uCPdDXzbdv) Join our Discord server to chat with others! + [Documentation](https://www.sea-ql.org/SeaORM) Integration examples: + [Actix Example](https://github.com/SeaQL/sea-orm/tree/master/examples/actix_example) + [Axum Example](https://github.com/SeaQL/sea-orm/tree/master/examples/axum_example) + [GraphQL Example](https://github.com/SeaQL/sea-orm/tree/master/examples/graphql_example) + [jsonrpsee Example](https://github.com/SeaQL/sea-orm/tree/master/examples/jsonrpsee_example) + [Loco Example](https://github.com/SeaQL/sea-orm/tree/master/examples/loco_example) / [Loco REST Starter](https://github.com/SeaQL/sea-orm/tree/master/examples/loco_starter) + [Poem Example](https://github.com/SeaQL/sea-orm/tree/master/examples/poem_example) + [Rocket Example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example) / [Rocket OpenAPI Example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_okapi_example) + [Salvo Example](https://github.com/SeaQL/sea-orm/tree/master/examples/salvo_example) + [Tonic Example](https://github.com/SeaQL/sea-orm/tree/master/examples/tonic_example) + [Seaography Example (Bakery)](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example) / [Seaography Example (Sakila)](https://github.com/SeaQL/seaography/tree/main/examples/sqlite) If you want a simple, clean example that fits in a single file that demonstrates the best of SeaORM, you can try: + [Quickstart](https://github.com/SeaQL/sea-orm/blob/master/examples/quickstart/src/main.rs) Let's have a quick walk through of the unique features of SeaORM. ## Expressive Entity format You don't have to write this by hand! Entity files can be generated from an existing database using `sea-orm-cli`, following is generated with `--entity-format dense` *(new in 2.0)*. ```rust mod user { use sea_orm::entity::prelude::*; #[sea_orm::model] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name = "user")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, #[sea_orm(unique)] pub email: String, #[sea_orm(has_one)] pub profile: HasOne, #[sea_orm(has_many)] pub posts: HasMany, } } mod post { use sea_orm::entity::prelude::*; #[sea_orm::model] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name = "post")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub user_id: i32, pub title: String, #[sea_orm(belongs_to, from = "user_id", to = "id")] pub author: BelongsTo, #[sea_orm(has_many, via = "post_tag")] // M-N relation with junction pub tags: HasMany, } } ``` ## Smart Entity Loader The Entity Loader intelligently uses join for 1-1 and data loader for 1-N relations, eliminating the N+1 problem even when performing nested queries. ```rust // join paths: // user -> profile // user -> post // post -> post_tag -> tag let smart_user = user::Entity::load() .filter_by_id(42) // shorthand for .filter(user::COLUMN.id.eq(42)) .with(profile::Entity) // 1-1 uses join .with((post::Entity, tag::Entity)) // 1-N uses data loader .one(db) .await? .unwrap(); // 3 queries are executed under the hood: // 1. SELECT FROM user JOIN profile WHERE id = $ // 2. SELECT FROM post WHERE user_id IN (..) // 3. SELECT FROM tag JOIN post_tag WHERE post_id IN (..) smart_user == user::ModelEx { id: 42, name: "Bob".into(), email: "bob@sea-ql.org".into(), profile: HasOne::loaded(Some(profile::ModelEx { picture: "image.jpg".into(), })), posts: HasMany::Loaded(vec![post::ModelEx { title: "Nice weather".into(), tags: HasMany::Loaded(vec![tag::ModelEx { tag: "sunny".into(), }]), }]), }; ``` ## ActiveModel: nested persistence made simple Persist an entire object graph: user, profile (1-1), posts (1-N), and tags (M-N) in a single operation using a fluent builder API. SeaORM automatically determines the dependencies and inserts or deletes objects in the correct order. This requires the SeaORM 2.0 dense entity format. ```rust // this creates the nested object as shown above: let user = user::ActiveModel::builder() .set_name("Bob") .set_email("bob@sea-ql.org") .set_profile(profile::ActiveModel::builder().set_picture("image.jpg")) .add_post( post::ActiveModel::builder() .set_title("Nice weather") .add_tag(tag::ActiveModel::builder().set_tag("sunny")), ) .save(db) .await?; ``` ## Schema first or Entity first? Your choice SeaORM provides a powerful migration system that lets you create tables, modify schemas, and seed data with ease. With SeaORM 2.0, you also get a first-class [Entity First Workflow](https://www.sea-ql.org/blog/2025-10-30-sea-orm-2.0/): simply define new entities or add columns to existing ones, and SeaORM will automatically detect the changes and create the new tables, columns, unique keys, and foreign keys. ```rust // SeaORM resolves foreign key dependencies and creates the tables in topological order. // Requires the `entity-registry` and `schema-sync` feature flags. db.get_schema_registry("my_crate::entity::*").sync(db).await; ``` ## Ergonomic Raw SQL Let SeaORM handle 95% of your transactional queries. For the remaining cases that are too complex to express, SeaORM still offers convenient support for writing raw SQL. ```rust let user = Item { name: "Bob" }; // nested parameter access let ids = [2, 3, 4]; // expanded by the `..` operator let user: Option = user::Entity::find() .from_raw_sql(raw_sql!( Sqlite, r#"SELECT "id", "name" FROM "user" WHERE "name" LIKE {user.name} AND "id" in ({..ids}) "# )) .one(db) .await?; ``` ## Synchronous Support [`sea-orm-sync`](https://crates.io/crates/sea-orm-sync) provides the full SeaORM API without requiring an async runtime, making it ideal for lightweight CLI programs with SQLite. See the [quickstart example](https://github.com/SeaQL/sea-orm/blob/master/sea-orm-sync/examples/quickstart/src/main.rs) for usage. ## Basics ### Select SeaORM models 1-N and M-N relationships at the Entity level, letting you traverse many-to-many links through a junction table in a single call. ```rust // find all models let cakes: Vec = Cake::find().all(db).await?; // find and filter let chocolate: Vec = Cake::find() .filter(Cake::COLUMN.name.contains("chocolate")) .all(db) .await?; // find one model let cheese: Option = Cake::find_by_id(1).one(db).await?; let cheese: cake::Model = cheese.unwrap(); // find related models (lazy) let fruit: Option = cheese.find_related(Fruit).one(db).await?; // find related models (eager): for 1-1 relations let cake_with_fruit: Vec<(cake::Model, Option)> = Cake::find().find_also_related(Fruit).all(db).await?; // find related models (eager): works for both 1-N and M-N relations let cake_with_fillings: Vec<(cake::Model, Vec)> = Cake::find() .find_with_related(Filling) // for M-N relations, two joins are performed .all(db) // rows are automatically consolidated by left entity .await?; ``` ### Nested Select Partial models prevent overfetching by letting you querying only the fields you need; it also makes writing deeply nested relational queries simple. ```rust use sea_orm::DerivePartialModel; #[derive(DerivePartialModel)] #[sea_orm(entity = "cake::Entity")] struct CakeWithFruit { id: i32, name: String, #[sea_orm(nested)] fruit: Option, // this can be a regular or another partial model } let cakes: Vec = Cake::find() .left_join(fruit::Entity) // no need to specify join condition .into_partial_model() // only the columns in the partial model will be selected .all(db) .await?; ``` ### Insert SeaORM's ActiveModel lets you work directly with Rust data structures and persist them through a simple API. It's easy to insert large batches of rows from different data sources. ```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: Active Record style let apple = apple.insert(db).await?; apple.id == 1; // insert one: repository style let result = Fruit::insert(apple).exec(db).await?; result.last_insert_id == 1; // insert many returning last insert id let result = Fruit::insert_many([apple, pear]).exec(db).await?; result.last_insert_id == Some(2); ``` ### Insert (advanced) You can take advantage of database specific features to perform upsert and idempotent insert. ```rust // insert many with returning (if supported by database) let models: Vec = Fruit::insert_many([apple, pear]) .exec_with_returning(db) .await?; models[0] == fruit::Model { id: 1, // database assigned value name: "Apple".to_owned(), cake_id: None, }; // insert with ON CONFLICT on primary key do nothing, with MySQL specific polyfill let result = Fruit::insert_many([apple, pear]) .on_conflict_do_nothing() .exec(db) .await?; matches!(result, TryInsertResult::Conflicted); ``` ### Update ActiveModel avoids race conditions by updating only the fields you've changed, never overwriting untouched columns. You can also craft complex bulk update queries with a fluent query building API. ```rust use sea_orm::sea_query::{Expr, Value}; let pear: Option = Fruit::find_by_id(1).one(db).await?; let mut pear: fruit::ActiveModel = pear.unwrap().into(); pear.name = Set("Sweet pear".to_owned()); // update value of a single field // update one: only changed columns will be updated let pear: fruit::Model = pear.update(db).await?; // update many: UPDATE "fruit" SET "cake_id" = "cake_id" + 2 // WHERE "fruit"."name" LIKE '%Apple%' Fruit::update_many() .col_expr(fruit::COLUMN.cake_id, fruit::COLUMN.cake_id.add(2)) .filter(fruit::COLUMN.name.contains("Apple")) .exec(db) .await?; ``` ### Save You can perform "insert or update" operation with ActiveModel, making it easy to compose transactional operations. ```rust let banana = fruit::ActiveModel { id: NotSet, name: Set("Banana".to_owned()), ..Default::default() }; // create, because primary key `id` is `NotSet` let mut banana = banana.save(db).await?; banana.id == Unchanged(2); banana.name = Set("Banana Mongo".to_owned()); // update, because primary key `id` is present let banana = banana.save(db).await?; ``` ### Delete The same ActiveModel API consistent with insert and update. ```rust // delete one: Active Record style let orange: Option = Fruit::find_by_id(1).one(db).await?; let orange: fruit::Model = orange.unwrap(); orange.delete(db).await?; // delete one: repository style let orange = fruit::ActiveModel { id: Set(2), ..Default::default() }; fruit::Entity::delete(orange).exec(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?; ``` ### Raw SQL Query The `raw_sql!` macro is like the `format!` macro but without the risk of SQL injection. It supports nested parameter interpolation, array and tuple expansion, and even repeating group, offering great flexibility in crafting complex queries. ```rust #[derive(FromQueryResult)] struct CakeWithBakery { name: String, #[sea_orm(nested)] bakery: Option, } #[derive(FromQueryResult)] struct Bakery { #[sea_orm(alias = "bakery_name")] name: String, } let cake_ids = [2, 3, 4]; // expanded by the `..` operator // can use many APIs with raw SQL, including nested select let cake: Option = CakeWithBakery::find_by_statement(raw_sql!( Sqlite, r#"SELECT "cake"."name", "bakery"."name" AS "bakery_name" FROM "cake" LEFT JOIN "bakery" ON "cake"."bakery_id" = "bakery"."id" WHERE "cake"."id" IN ({..cake_ids})"# )) .one(db) .await?; ``` ## 🧭 Seaography: instant GraphQL API [Seaography](https://github.com/SeaQL/seaography) is a GraphQL framework built for SeaORM. Seaography allows you to build GraphQL resolvers quickly. With just a few commands, you can launch a fullly-featured GraphQL server from SeaORM entities, complete with filter, pagination, relational queries and mutations! Look at the [Seaography Example](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example) to learn more. ## πŸ–₯️ SeaORM Pro: Professional Admin Panel [SeaORM Pro](https://github.com/SeaQL/sea-orm-pro/) is an admin panel solution allowing you to quickly and easily launch an admin panel for your application - frontend development skills not required, but certainly nice to have! SeaORM Pro has been updated to support the latest features in SeaORM 2.0. Features: + Full CRUD + Built on React + GraphQL + Built-in GraphQL resolver + Customize the UI with TOML config + Role Based Access Control *(new in 2.0)* Read the [Getting Started](https://www.sea-ql.org/sea-orm-pro/docs/install-and-config/getting-started/) guide to learn more. ![](https://raw.githubusercontent.com/SeaQL/sea-orm/refs/heads/master/docs/sea-orm-pro-dark.png#gh-dark-mode-only) ![](https://raw.githubusercontent.com/SeaQL/sea-orm/refs/heads/master/docs/sea-orm-pro-light.png#gh-light-mode-only) ## SQL Server Support [SQL Server for SeaORM](https://www.sea-ql.org/SeaORM-X/) offers the same SeaORM API for MSSQL. We ported all test cases and examples, complemented by MSSQL specific documentation. If you are building enterprise software, you can [request commercial access](https://forms.office.com/r/1MuRPJmYBR). It is currently based on SeaORM 1.0, but we will offer free upgrade to existing users when SeaORM 2.0 is finalized. ## Releases SeaORM 2.0 has reached its release candidate phase. We'd love for you to try it out and help shape the final release by [sharing your feedback](https://github.com/SeaQL/sea-orm/discussions/). + [Change Log](https://github.com/SeaQL/sea-orm/tree/master/CHANGELOG.md) SeaORM 2.0 is shaping up to be our most significant release yet - with a few breaking changes, plenty of enhancements, and a clear focus on developer experience. + [A Sneak Peek at SeaORM 2.0](https://www.sea-ql.org/blog/2025-09-16-sea-orm-2.0/) + [SeaORM 2.0: A closer look](https://www.sea-ql.org/blog/2025-09-24-sea-orm-2.0/) + [Role Based Access Control in SeaORM 2.0](https://www.sea-ql.org/blog/2025-09-30-sea-orm-rbac/) + [Seaography 2.0: A Powerful and Extensible GraphQL Framework](https://www.sea-ql.org/blog/2025-10-08-seaography/) + [SeaORM 2.0: New Entity Format](https://www.sea-ql.org/blog/2025-10-20-sea-orm-2.0/) + [SeaORM 2.0: Entity First Workflow](https://www.sea-ql.org/blog/2025-10-30-sea-orm-2.0/) + [SeaORM 2.0: Strongly-Typed Column](https://www.sea-ql.org/blog/2025-11-11-sea-orm-2.0/) + [What's new in SeaORM Pro 2.0](https://www.sea-ql.org/blog/2025-11-21-whats-new-in-seaormpro-2.0/) + [SeaORM 2.0: Nested ActiveModel](https://www.sea-ql.org/blog/2025-11-25-sea-orm-2.0/) + [A walk-through of SeaORM 2.0](https://www.sea-ql.org/blog/2025-12-05-sea-orm-2.0/) + [How we made SeaORM synchronous](https://www.sea-ql.org/blog/2025-12-12-sea-orm-2.0/) + [SeaORM 2.0 Migration Guide](https://www.sea-ql.org/blog/2026-01-12-sea-orm-2.0/) + [SeaORM now supports Arrow & Parquet](https://www.sea-ql.org/blog/2026-02-22-sea-orm-arrow/) + [SeaORM 2.0 with SQL Server Support](https://www.sea-ql.org/blog/2026-02-25-sea-orm-x/) If you make extensive use of SeaQuery, we recommend checking out our blog post on SeaQuery 1.0 release: + [The road to SeaQuery 1.0](https://www.sea-ql.org/blog/2025-08-30-sea-query-1.0/) ## License Licensed under either of - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ## Contribution 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. We invite you to participate, contribute and together help build Rust's future. A big shout out to our contributors! [![Contributors](https://opencollective.com/sea-orm/contributors.svg?width=1000&button=false)](https://github.com/SeaQL/sea-orm/graphs/contributors) ## Who's using SeaORM? Here is a short list of awesome open source software built with SeaORM. Feel free to [submit yours](https://github.com/SeaQL/sea-orm/blob/master/COMMUNITY.md#built-with-seaorm)! | Project | GitHub | Tagline | |---------|--------|---------| | [Zed](https://github.com/zed-industries/zed) | ![GitHub stars](https://img.shields.io/github/stars/zed-industries/zed.svg?style=social) | A high-performance, multiplayer code editor | | [Servo](https://github.com/servo/servo) | ![GitHub stars](https://img.shields.io/github/stars/servo/servo.svg?style=social) | The Servo Parallel Browser Engine Project | | [OpenObserve](https://github.com/openobserve/openobserve) | ![GitHub stars](https://img.shields.io/github/stars/openobserve/openobserve.svg?style=social) | Open-source observability platform | | [RisingWave](https://github.com/risingwavelabs/risingwave) | ![GitHub stars](https://img.shields.io/github/stars/risingwavelabs/risingwave.svg?style=social) | Stream processing and management platform | | [Warpgate](https://github.com/warp-tech/warpgate) | ![GitHub stars](https://img.shields.io/github/stars/warp-tech/warpgate.svg?style=social) | Smart SSH bastion that works with any SSH client | | [LLDAP](https://github.com/nitnelave/lldap) | ![GitHub stars](https://img.shields.io/github/stars/nitnelave/lldap.svg?style=social) | A light LDAP server for user management | | [Svix](https://github.com/svix/svix-webhooks) | ![GitHub stars](https://img.shields.io/github/stars/svix/svix-webhooks.svg?style=social) | The enterprise ready webhooks service | | [Ryot](https://github.com/IgnisDa/ryot) | ![GitHub stars](https://img.shields.io/github/stars/ignisda/ryot.svg?style=social) | The only self hosted tracker you will ever need | | [OctoBase](https://github.com/toeverything/OctoBase) | ![GitHub stars](https://img.shields.io/github/stars/toeverything/OctoBase.svg?style=social) | A light-weight, scalable, offline collaborative data backend | | [System Initiative](https://github.com/systeminit/si) | ![GitHub stars](https://img.shields.io/github/stars/systeminit/si.svg?style=social) | DevOps Automation Platform | ## Sponsorship [SeaQL.org](https://www.sea-ql.org/) is an independent open-source organization run by passionate developers. If you feel generous, a small donation via [GitHub Sponsor](https://github.com/sponsors/SeaQL) will be greatly appreciated, and goes a long way towards sustaining the organization. ### Silver Sponsors We're grateful to our silver sponsors: Digital Ocean, for sponsoring our servers. And JetBrains, for sponsoring our IDE.
## Mascot A friend of Ferris, Terres the hermit crab is the official mascot of SeaORM. His hobby is collecting shells. Terres ## πŸ¦€ Rustacean Sticker Pack The Rustacean Sticker Pack is the perfect way to express your passion for Rust. Our stickers are made with a premium water-resistant vinyl with a unique matte finish. Sticker Pack Contents: + Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography + Mascots: Ferris the Crab x 3, Terres the Hermit Crab + The Rustacean wordmark [Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) All proceeds contributes directly to the ongoing development of SeaQL projects. Rustacean Sticker Pack by SeaQL