ORM para Rust: comparação detalhada e exemplos de uso
O ecossistema Rust oferece várias soluções poderosas para trabalhar com bancos de dados. Neste artigo, vamos analisar três dos ORMs (Object-Relational Mapping) mais populares para Rust: Diesel, SeaORM e SQLx. Cada um deles tem seus pontos fortes e é adequado para diferentes cenários. Vamos compará-los por características-chave e fornecer exemplos práticos de código.
1. Diesel — ORM clássico com desempenho máximo
Diesel é o ORM mais maduro no ecossistema Rust. Ele funciona de forma síncrona (com suporte a assincronicidade via diesel-async) e é conhecido por seu alto desempenho e segurança de tipos.
Principais características:
- Total segurança de tipos: erros SQL são detectados em tempo de compilação
- Suporte a PostgreSQL, MySQL, SQLite
- Geração de esquema através da ferramenta CLI
diesel_cli - Otimizado para consultas complexas e transações
Exemplo de código com Diesel:
// Definição do modelo#[derive(Queryable, Insertable)]#[diesel(table_name = crate::schema::users)]struct User { id: i32, name: String, email: String,}
// Inserir um novo usuáriofn create_user(conn: &mut PgConnection, name: &str, email: &str) -> User { let new_user = NewUser { name, email }; diesel::insert_into(users::table) .values(&new_user) .get_result(conn) .expect("Error saving new user")}
// Consultar todos os usuáriosfn get_all_users(conn: &mut PgConnection) -> Vec<User> { users::table .load::<User>(conn) .expect("Error loading users")}2. SeaORM — ORM assíncrono com modelo ativo
SeaORM é um ORM assíncrono moderno, inspirado no Entity Framework e no Active Record. Ele fornece uma API conveniente para construir consultas e suporta migrações "prontas para uso".
Principais características:
- Assincronicidade por padrão (baseado em Tokio)
- Modelo ativo: é possível chamar métodos nas entidades
- Suporte a relacionamentos (has_many, belongs_to, many_to_many)
- Migrações integradas e utilitário CLI
Exemplo de código com SeaORM:
use sea_orm::{entity::prelude::*, Database, EntityTrait};
// Definição da entidade#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]#[sea_orm(table_name = "users")]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 {}
// Uso no códigoasync fn run() { let db = Database::connect("postgres://user:pass@localhost/db").await.unwrap(); // Inserir let user = ActiveModel { name: Set("Alice".to_owned()), email: Set("alice@example.com".to_owned()), ..Default::default() }; let result = Entity::insert(user).exec(&db).await.unwrap(); // Selecionar todos let users: Vec<Model> = Entity::find().all(&db).await.unwrap();}3. SQLx — não é um ORM, mas um driver SQL assíncrono com verificação em tempo de compilação
SQLx ocupa uma posição intermediária: não é um ORM completo, mas fornece ferramentas poderosas para trabalhar com SQL com verificação de consultas durante a compilação. É ideal para quem prefere escrever SQL puro, mas quer evitar erros.
Principais características:
- Assíncrono (Tokio, async-std)
- Verificação de consultas SQL em tempo de compilação através da macro
sqlx::query! - Suporte a PostgreSQL, MySQL, SQLite, MSSQL
- Leve, sem a magia de um ORM