Exposed لـ Kotlin: دليل شامل مع أمثلة

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

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

ابدأ الدورة

ما هو Exposed ولماذا نحتاجه؟

\n\n

Exposed هي مكتبة ORM (تعيين الكائنات العلائقية) خفيفة الوزن ولكنها قوية للغة البرمجة Kotlin، تم تطويرها بواسطة شركة JetBrains. توفر طريقتين رئيسيتين للعمل مع قواعد البيانات: DSL (لغة خاصة بالمجال) و DAO (كائنات الوصول إلى البيانات).

\n\n

لماذا نحتاج Exposed؟

\n
    \n
  • أمان الأنواع: على عكس استعلامات SQL الخام، يستخدم Exposed بنى Kotlin المحددة الأنواع، مما يسمح باكتشاف الأخطاء في مرحلة الترجمة.
  • \n
  • الإيجاز: الكود في Exposed أقصر بكثير وأكثر قابلية للقراءة من استعلامات SQL المكافئة أو كود Java مع JPA.
  • \n
  • الأداء: لا يستخدم Exposed الانعكاس (reflection) أو الكائنات الوكيلة (proxy) مثل Hibernate، مما يجعله سريعًا جدًا وقابلًا للتنبؤ.
  • \n
  • المرونة: يمكنك التبديل بسهولة بين DSL (للاستعلامات المعقدة) و DAO (لعمليات CRUD البسيطة) ضمن مشروع واحد.
  • \n
  • دعم قواعد بيانات متعددة: PostgreSQL, MySQL, MariaDB, SQLite, H2, Oracle, SQL Server.
  • \n
\n\n

تثبيت Exposed

\n\n

يتم تثبيت Exposed عبر نظام البناء Gradle أو Maven. أضف التبعيات التالية إلى ملف build.gradle.kts الخاص بك:

\n\n
dependencies {\n    // المكتبة الأساسية\n    implementation("org.jetbrains.exposed:exposed-core:0.44.1")\n    // DSL للاستعلامات\n    implementation("org.jetbrains.exposed:exposed-dao:0.44.1")\n    // مشغل JDBC لقاعدة البيانات الخاصة بك (مثال لـ PostgreSQL)\n    implementation("org.postgresql:postgresql:42.7.1")\n    // تجمع اتصالات HikariCP (موصى به)\n    implementation("com.zaxxer:HikariCP:5.1.0")\n    // تسجيل SQL (اختياري)\n    implementation("ch.qos.logback:logback-classic:1.4.14")\n}
\n\n

لـ Maven (pom.xml):

\n\n
<dependency>\n    <groupId>org.jetbrains.exposed</groupId>\n    <artifactId>exposed-core</artifactId>\n    <version>0.44.1</version>\n</dependency>
\n\n

بداية سريعة: مثال كود

\n\n

لننشئ تطبيقًا بسيطًا لإدارة المهام (ToDo):

\n\n
import org.jetbrains.exposed.sql.*\nimport org.jetbrains.exposed.sql.transactions.transaction\nimport org.jetbrains.exposed.sql.SqlExpressionBuilder.eq\nimport java.time.LocalDateTime\n\n// 1. تعريف الجدول\nobject Tasks : Table() {\n    val id = integer("id").autoIncrement()\n    val title = varchar("title", 255)\n    val description = text("description").nullable()\n    val isCompleted = bool("is_completed").default(false)\n    val createdAt = datetime("created_at").default(LocalDateTime.now())\n\n    override val primaryKey = PrimaryKey(id)\n}\n\n// 2. Data class للراحة\ndata class Task(\n    val id: Int,\n    val title: String,\n    val description: String?,\n    val isCompleted: Boolean,\n    val createdAt: LocalDateTime\n)\n\nfun main() {\n    // 3. الاتصال بقاعدة البيانات (H2 في الذاكرة كمثال)\n    Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")\n\n    transaction {\n        // 4. إنشاء الجدول\n        SchemaUtils.create(Tasks)\n\n        // 5. إدراج البيانات\n        val insertId = Tasks.insert {\n            it[title] = "دراسة Exposed"\n            it[description] = "قراءة التوثيق وكتابة مثال"\n        } get Tasks.id\n\n        println("تم إدراج مهمة بالمعرف: $insertId")\n\n        // 6. اختيار جميع المهام\n        val allTasks = Tasks.selectAll().map { row ->\n            Task(\n                id = row[Tasks.id],\n                title = row[Tasks.title],\n                description = row[Tasks.description],\n                isCompleted = row[Tasks.isCompleted],\n                createdAt = row[Tasks.createdAt]\n            )\n        }\n        println("جميع المهام: $allTasks")\n\n        // 7. تحديث مهمة\n        Tasks.updat                    

توصيات