SeaORM — ORM для Rust, с которой приятно работать

16 Apr, 2026

Если вы когда-нибудь писали веб-сервисы на Rust, то знаете это чувство: с одной стороны — невероятная производительность и безопасность, с другой — многословность и бойлерплейт, особенно при работе с базами данных. Кажется, что за скорость и надёжность приходится платить удобством, к которому мы привыкли в мире Python с Django или Ruby с Rails. Но что, если я скажу, что есть инструмент, который пытается это исправить?

Сегодня мы посмотрим на SeaORM — асинхронную и динамическую ORM для Rust, которая ставит во главу угла опыт разработчика. Её авторы не скрывают, что вдохновлялись популярными ORM из других экосистем, и это чувствуется с первых строк кода. Давайте разберёмся, что делает её такой особенной и почему на неё стоит обратить внимание.

SeaORM Banner

Что это за зверь и с чем его едят?

SeaORM — это библиотека, которая помогает вашему Rust-коду "общаться" с реляционными базами данных (PostgreSQL, MySQL, SQLite) на высоком уровне. Вместо того чтобы писать сырые SQL-запросы в виде строк, вы работаете с Rust-структурами и методами. Это не только уменьшает количество ошибок, но и делает код гораздо более читаемым и поддерживаемым.

Проект активно развивается, имеет огромное сообщество (почти 250 тысяч загрузок в неделю!) и используется в продакшене как стартапами, так и крупными компаниями. А ещё у проекта есть милый маскот — рак-отшельник Террес, который коллекционирует ракушки. Мелочь, а приятно.

Маскот SeaORM — рак-отшельник Террес

Ключевые возможности: за что её любить?

Давайте пройдёмся по самым интересным фичам, которые выделяют SeaORM на фоне других инструментов.

1. ActiveModel: работа с данными как с объектами

Если вы пришли из мира Ruby on Rails или Django, концепция ActiveModel покажется вам до боли знакомой. Это реализация паттерна Active Record, где каждая структура — это не просто набор данных, а полноценный объект, который умеет себя сохранять, обновлять и удалять.

Посмотрите, насколько это интуитивно:

// Создаём новую запись
let apple = fruit::ActiveModel {
    name: Set("Apple".to_owned()),
    ..Default::default()
};
let apple_model = apple.insert(db).await?;

// Теперь обновляем её
let mut apple_active_model: fruit::ActiveModel = apple_model.into();
apple_active_model.name = Set("Sweet Apple".to_owned());
let updated_apple = apple_active_model.update(db).await?;

Больше не нужно вручную собирать UPDATE запросы. Вы просто меняете поля в структуре и вызываете метод .update(). ORM сама поймёт, какие поля изменились, и обновит только их, что помогает избежать состояний гонки.

2. Прощай, проблема N+1!

Одна из самых частых проблем при работе с ORM — это проблема "N+1 запроса". Это когда для получения N дочерних записей выполняется один запрос на получение родительских и ещё N запросов для каждой дочерней. Это может серьёзно ударить по производительности.

В SeaORM есть Smart Entity Loader, который элегантно решает эту проблему. Он достаточно умён, чтобы для связей "один-к-одному" использовать JOIN, а для "один-ко-многим" — более эффективный подход с одним дополнительным запросом (Data Loader).

// Загружаем пользователя, его профиль (1-к-1) и все его посты с тегами (1-ко-многим и многие-ко-многим)
let smart_user = user::Entity::load()
    .filter_by_id(42)
    .with(profile::Entity) // 1-1 использует JOIN
    .with((post::Entity, tag::Entity)) // 1-N и M-N используют Data Loader
    .one(db)
    .await?
    .unwrap();

// Под капотом выполнится всего 3 запроса вместо N+1:
// 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 (...)

Это позволяет строить сложные вложенные запросы, не беспокоясь о том, что вы положите базу данных.

3. Schema-first или Entity-first? Выбирайте сами

Разные проекты требуют разных подходов к управлению схемой базы данных.

  • Schema-first: Вы сначала пишете миграции, которые описывают изменения в БД, а затем обновляете код. Это классический, надёжный подход.
  • Entity-first: Вы описываете сущности прямо в Rust-коде, а ORM сама генерирует и применяет миграции, чтобы привести БД в соответствие с кодом.

SeaORM поддерживает оба подхода! Вы можете писать миграции вручную для полного контроля или позволить библиотеке делать грязную работу за вас, просто описав модели в коде. Это даёт невероятную гибкость как для новых проектов, так и для работы с уже существующими базами данных.

4. Вся мощь SQL, когда это необходимо

Ни одна ORM не может покрыть 100% всех возможных SQL-запросов. Иногда нужно написать что-то действительно сложное. SeaORM и здесь не подводит, предлагая безопасный и удобный макрос raw_sql!. Он работает как format!, но защищает от SQL-инъекций и поддерживает удобную подстановку параметров.

let user = Item { name: "Bob" };
let ids = [2, 3, 4];

let user: Option<user::Model> = 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?;

Обратите внимание на синтаксис {user.name} и {..ids} — макрос сам развернёт массив в список (?, ?, ?) и подставит параметры, сохранив запрос безопасным.

Больше чем просто ORM: целая экосистема

Что действительно впечатляет в SeaQL, так это то, что они строят целую экосистему инструментов вокруг своей ORM.

Seaography: GraphQL API в пару команд

Представьте, что у вас уже есть модели SeaORM, и вам нужен GraphQL API. С Seaography это делается за минуты. Инструмент анализирует ваши сущности и генерирует полнофункциональный GraphQL-сервер с фильтрацией, пагинацией и связями.

Пример работы Seaography

SeaORM Pro: Готовая админка

Ещё один мощный инструмент в экосистеме — SeaORM Pro. Это готовое решение для создания админ-панели для вашего приложения. Вам не нужно быть фронтенд-разработчиком — достаточно описать конфигурацию в TOML-файле, и вы получите полноценный CRUD-интерфейс с ролевой моделью доступа.

Выводы: кому и зачем?

SeaORM — это не просто "ещё одна ORM". Это зрелый, продуманный и невероятно удобный инструмент, который делает разработку на Rust значительно приятнее.

Кому он особенно подойдёт:

  • Rust-разработчикам, которые строят веб-сервисы и API и устали от бойлерплейта.
  • Командам, мигрирующим с Python, Ruby или Node.js, которые ищут знакомые и удобные паттерны работы с данными.
  • Проектам, где важна и производительность, и скорость разработки. SeaORM доказывает, что эти два понятия не должны быть взаимоисключающими.

Если вы пишете на Rust или только присматриваетесь к нему для своего следующего веб-проекта, я настоятельно рекомендую взглянуть на репозиторий SeaORM и попробовать их Quickstart пример. Возможно, это именно тот инструмент, который вернёт вам радость от работы с базами данных.