ORM لـ Rust: مقارنة وأمثلة لـ Diesel، SeaORM، SQLx

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

ORM لـ Rust: مقارنة شاملة وأمثلة استخدام



يقدم نظام Rust البيئي عدة حلول قوية للعمل مع قواعد البيانات. في هذه المقالة، سنقارن بالتفصيل بين ثلاث طرق رئيسية: Diesel (ORM متزامن، قابل للتجميع)، SeaORM (غير متزامن، مرن)، و SQLx (بسيط، مع التحقق من الاستعلامات في مرحلة التجميع). ستتعرف على الأداة المناسبة لمهامك المحددة، وسترى أمثلة كود عملية.



1. Diesel — ORM متزامن موثوق

Diesel هو أكثر ORM نضجًا في Rust. ميزته الرئيسية هي سلامة الأنواع في مرحلة التجميع. يتم التحقق من جميع استعلامات SQL أثناء البناء، مما يلغي فئة كاملة من الأخطاء. يعمل بشكل متزامن فقط، ولكن يمكن تنظيم مجموعة اتصالات باستخدام tokio.



مثال على استخدام Diesel:

// models.rs#[derive(Queryable, Insertable)]#[table_name = "users"]pub struct User {    pub id: i32,    pub name: String,    pub email: String,}

// main.rsuse diesel::prelude::*;use diesel::dsl::insert_into;

fn main() { let conn = PgConnection::establish("postgres://user:pass@localhost/db") .expect("فشل الاتصال بقاعدة البيانات");

let new_user = User { id: 0, name: "Alice".into(), email: "alice@example.com".into(), };

let inserted = insert_into(users::table) .values(&new_user) .get_result::<User>(&conn) .expect("فشل الإدراج");

println!("تم إنشاء المستخدم: {}", inserted.name);}


المزايا: أداء أقصى، كتابة صارمة، ترحيلات مدمجة.

العيوب: متزامن، إعداد معقد، لا يدعم async بشكل افتراضي.



2. SeaORM — غير متزامن ومرن

SeaORM هو ORM حديث غير متزامن مبني على sqlx. يدعم tokio و async-std. يوفر واجهة برمجة تطبيقات غنية لعمليات CRUD، والعلاقات (واحد إلى واحد، واحد إلى متعدد) والترحيلات. مثالي لتطبيقات الويب على Actix أو Axum.



مثال مع SeaORM:

use sea_orm::*;use sea_orm::entity::prelude::*;

#[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 {}

// الاستخدامasync fn create_user(db: &DatabaseConnection) -> Result<(), DbErr> { let user = ActiveModel { name: Set("Bob".to_owned()), email: Set("bob@example.com".to_owned()), ..Default::default() }; let result = user.insert(db).await?; println!("تم إنشاء المستخدم بالمعرف: {}", result.id); Ok(())}


المزايا: async كامل، دعم PostgreSQL، MySQL، SQLite، ترحيلات بسيطة.

العيوب: أبطأ من Diesel في الاختبارات الاصطناعية، تبعيات أكثر.



3. SQLx — خفيف وآمن

SQLx ليس ORM بالمعنى التقليدي، بل هو مشغل SQL غير متزامن مع التحقق من الاستعلامات في مرحلة التجميع. تكتب SQL نقيًا، ويتحقق SQLx من بناء الجملة وأنواع الوسائط. يدعم PostgreSQL، MySQL، SQLite. خيار ممتاز إذا كنت تفضل التحكم الكامل في الاستعلامات.



مثال SQLx:

use sqlx::postgres::PgPool;

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

#[tokio::main]async fn main() -> Result<(), sqlx::Error> { let pool = PgPool::connect("postgres://user:pass@localhost/db").await?;

let user = sqlx::query_as::<_, User>( "SELECT id, name, email FROM users WHERE email = $1"

توصيات