ORM для Rust: сравнение Diesel, SeaORM, SQLx и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

ORM для Rust: сравнение и примеры

Экосистема Rust предлагает несколько мощных решений для работы с базами данных. В этой статье мы сравним три популярных ORM-подобных инструмента: Diesel, SeaORM и SQLx. Каждый из них имеет свою философию и область применения. Рассмотрим их особенности, производительность и приведём практические примеры.

1. Diesel — классический ORM с безопасностью типов

Diesel — самый зрелый ORM для Rust, построенный на принципе «безопасность типов во время компиляции». Он требует явного описания схемы через миграции и генерирует строго типизированные структуры.

Особенности:

  • Компиляция проверяет корректность запросов (ошибки SQL — на этапе сборки)
  • Поддержка PostgreSQL, MySQL, SQLite
  • Синхронный движок (для асинхронности требуется diesel-async)
  • Собственный DSL для построения запросов

Пример кода (Diesel + PostgreSQL):

// models.rs
use diesel::prelude::*;

#[derive(Queryable, Selectable)]
#[diesel(table_name = crate::schema::users)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: String,
}

// main.rs
use diesel::prelude::*;
use diesel::pg::PgConnection;

fn get_user(conn: &mut PgConnection, user_id: i32) -> Option<User> {
    use crate::schema::users::dsl::*;
    users.filter(id.eq(user_id))
        .first::<User>(conn)
        .ok()
}

Когда выбрать: для проектов, где критична безопасность запросов на этапе компиляции, и вы готовы к строгой схеме.

2. SeaORM — асинхронный ORM с ActiveRecord-подходом

SeaORM — современный асинхронный ORM, вдохновлённый Ruby on Rails. Поддерживает как код-ферст, так и генерацию сущностей из существующей БД.

Особенности:

  • Полная асинхронность (Tokio, async-std)
  • Поддержка PostgreSQL, MySQL, SQLite, а также CockroachDB
  • Миграции, связи (has_many, belongs_to), пагинация
  • Генератор кода sea-orm-cli

Пример кода (SeaORM + PostgreSQL):

use sea_orm::*;
use entity::user;

async fn find_user(db: &DatabaseConnection, user_id: i32) -> Result<Option<user::Model>, DbErr> {
    user::Entity::find_by_id(user_id)
        .one(db)
        .await
}

// Использование
async fn example() {
    let db = Database::connect("postgres://user:pass@localhost/db").await.unwrap();
    if let Some(user) = find_user(&db, 42).await.unwrap() {
        println!("User: {} ({})", user.name, user.email);
    }
}

Когда выбрать: для асинхронных веб-приложений (Actix, Axum), где нужна активная разработка и богатый функционал «из коробки».

3. SQLx — «почти ORM» с максимальной гибкостью

SQLx — не совсем ORM, а скорее асинхронный SQL-клиент с проверкой запросов. Он позволяет писать чистый SQL, но проверяет его корректность на этапе компиляции.

Особенности:

  • Проверка запросов во время компиляции (через макрос sqlx::query!)
  • Полная асинхронность
  • Поддержка PostgreSQL, MySQL, SQLite, MSSQL
  • Поддержка JSON, миграций, пула соединений

Пример кода (SQLx + PostgreSQL):

use sqlx::PgPool;

#[derive(sqlx::FromRow)]
struct User {
    id: i32,
    name: String,
    email: String,
}

async fn get_user(pool: &PgPool, user_id: i32) -> Result<Option<User>, sqlx::Error> {
    sqlx::query_as::<_, User>("SELECT id, name, email FROM users WHERE id = $1")
        .bind(user_id)
        .fetch_optional(pool)
        .await
}

Когда выбрать: если вы предпочитаете писать SQL вручную, но хотите проверку типов и асинхронность. Отлично подходит для сложных запросов.

Сравнительная таблица

  • Тип проверки: Diesel — компиляция; SeaORM — runtime + частичная ком

Рекомендаций