ORM für Rust: Vergleich und Beispiele
Das Rust-Ökosystem bietet mehrere leistungsstarke Lösungen für die Arbeit mit Datenbanken. In diesem Artikel vergleichen wir drei beliebte ORM-ähnliche Tools: Diesel, SeaORM und SQLx. Jedes hat seine eigene Philosophie und seinen Anwendungsbereich. Wir betrachten ihre Funktionen, Leistung und geben praktische Beispiele.
1. Diesel — klassisches ORM mit Typsicherheit
Diesel ist das ausgereifteste ORM für Rust, das auf dem Prinzip der „Typsicherheit zur Kompilierzeit“ basiert. Es erfordert eine explizite Schemabeschreibung durch Migrationen und generiert streng typisierte Strukturen.
Funktionen:
- Die Kompilierung prüft die Korrektheit von Abfragen (SQL-Fehler — bereits zur Build-Zeit)
- Unterstützung für PostgreSQL, MySQL, SQLite
- Synchroner Kern (für Asynchronität wird
diesel-asyncbenötigt) - Eigene DSL zum Erstellen von Abfragen
Codebeispiel (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()}Wann wählen: für Projekte, bei denen die Abfragesicherheit zur Kompilierzeit entscheidend ist und Sie bereit für ein strenges Schema sind.
2. SeaORM — asynchrones ORM mit ActiveRecord-Ansatz
SeaORM ist ein modernes asynchrones ORM, inspiriert von Ruby on Rails. Es unterstützt sowohl Code-First als auch die Generierung von Entitäten aus einer bestehenden Datenbank.
Funktionen:
- Vollständige Asynchronität (Tokio, async-std)
- Unterstützung für PostgreSQL, MySQL, SQLite sowie CockroachDB
- Migrationen, Beziehungen (has_many, belongs_to), Paginierung
- Code-Generator
sea-orm-cli
Codebeispiel (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}
// Verwendungasync fn example() { let db = Database::connect("postgres://user:pass@localhost/db").await.unwrap(); if let Some(user) = find_user(&db, 42).await.unwrap() { println!("Benutzer: {} ({})", user.name, user.email); }}Wann wählen: für asynchrone Webanwendungen (Actix, Axum), bei denen eine aktive Entwicklung und ein umfangreicher Funktionsumfang „out of the box“ benötigt werden.
3. SQLx — „Fast ORM“ mit maximaler Flexibilität
SQLx ist nicht ganz ein ORM, sondern eher ein asynchroner SQL-Client mit Abfrageprüfung. Es erlaubt das Schreiben von reinem SQL, prüft aber dessen Korrektheit zur Kompilierzeit.
Funktionen:
- Überprüfung von Abfragen zur Kompilierzeit (über das Makro
sqlx::query!) - Vollständige Asynchronität
- Unterstützung für PostgreSQL, MySQL, SQLite, MSSQL
- Unterstützung für JSON, Migrationen, Verbindungspools
Codebeispiel (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}Wann wählen: wenn Sie es bevorzugen, SQL zu schreiben