ORM para Rust: comparativa y ejemplos
El ecosistema de Rust ofrece varias soluciones potentes para trabajar con bases de datos. En este artículo compararemos tres herramientas similares a ORM populares: Diesel, SeaORM y SQLx. Cada una tiene su propia filosofía y ámbito de aplicación. Analizaremos sus características, rendimiento y proporcionaremos ejemplos prácticos.
1. Diesel — ORM clásico con seguridad de tipos
Diesel es el ORM más maduro para Rust, construido sobre el principio de "seguridad de tipos en tiempo de compilación". Requiere una descripción explícita del esquema mediante migraciones y genera estructuras fuertemente tipadas.
Características:
- La compilación verifica la corrección de las consultas (errores SQL en etapa de compilación)
- Soporte para PostgreSQL, MySQL, SQLite
- Motor síncrono (para asincronía se requiere
diesel-async) - DSL propio para construir consultas
Ejemplo de código (Diesel + PostgreSQL):
// models.rsuse 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.rsuse 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()}Cuándo elegirlo: para proyectos donde la seguridad de las consultas en tiempo de compilación es crítica y estás dispuesto a usar un esquema estricto.
2. SeaORM — ORM asíncrono con enfoque ActiveRecord
SeaORM es un ORM asíncrono moderno, inspirado en Ruby on Rails. Soporta tanto code-first como generación de entidades a partir de una base de datos existente.
Características:
- Asincronía completa (Tokio, async-std)
- Soporte para PostgreSQL, MySQL, SQLite y CockroachDB
- Migraciones, relaciones (has_many, belongs_to), paginación
- Generador de código
sea-orm-cli
Ejemplo de código (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}
// Usoasync 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); }}Cuándo elegirlo: para aplicaciones web asíncronas (Actix, Axum) donde se necesita un desarrollo activo y una funcionalidad rica "lista para usar".
3. SQLx — "casi ORM" con máxima flexibilidad
SQLx no es exactamente un ORM, sino más bien un cliente SQL asíncrono con verificación de consultas. Permite escribir SQL puro, pero verifica su corrección en tiempo de compilación.
Características:
- Verificación de consultas en tiempo de compilación (mediante la macro
sqlx::query!) - Asincronía completa
- Soporte para PostgreSQL, MySQL, SQLite, MSSQL
- Soporte para JSON, migraciones, pool de conexiones
Ejemplo de código (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}Cuándo elegirlo: si prefieres escribir SQL
También en la biblioteca
gRPC en Rust: bibliotecas Tonic y Grpc-rs con ejemplos
Planificador de tareas en C# (.NET): Quartz.NET y System.Threading.Timer
Cliente Redis (go-redis) para Go: guía completa con ejemplos
Monitoreo de aplicaciones TypeScript: bibliotecas, herramientas y configuración