مقدمة: لماذا يعتبر Kotlin وقواعد البيانات ثنائيًا مثاليًا
Kotlin هي لغة حديثة ذات كتابة ثابتة تعمل فوق JVM. بفضل تركيبها المختصر، وأمان القيم الخالية (null safety)، والتوافق الكامل مع Java، أصبحت Kotlin واحدة من أسرع اللغات نموًا لتطوير الواجهات الخلفية. في هذه المقالة، سنشرح كيفية الاتصال وتنفيذ عمليات CRUD مع اثنين من أنظمة إدارة قواعد البيانات الشائعة: قاعدة البيانات العلائقية PostgreSQL وقاعدة البيانات المستندية MongoDB.
سننظر في نهجين رئيسيين: استخدام مكتبة Exposed لـ SQL وإطار العمل KMongo للعمل مع MongoDB. جميع أمثلة الكود مكتوبة بلغة Kotlin الخالصة وجاهزة للتشغيل.
1. العمل مع PostgreSQL عبر مكتبة Exposed
1.1. إعداد التبعيات
للبدء، أضف التبعيات التالية إلى ملف build.gradle.kts:
dependencies { implementation("org.jetbrains.exposed:exposed-core:0.44.0") implementation("org.jetbrains.exposed:exposed-dao:0.44.0") implementation("org.jetbrains.exposed:exposed-jdbc:0.44.0") implementation("org.postgresql:postgresql:42.6.0") implementation("com.zaxxer:HikariCP:5.0.1")}HikariCP هو مجمع اتصالات عالي الأداء سنستخدمه لإدارة الاتصالات بقاعدة البيانات.
1.2. الاتصال بقاعدة البيانات
لنقم بإنشاء كائن لإدارة الاتصال:
import com.zaxxer.hikari.HikariConfigimport com.zaxxer.hikari.HikariDataSourceimport org.jetbrains.exposed.sql.Database
object DatabaseFactory { fun init() { val config = HikariConfig().apply { driverClassName = "org.postgresql.Driver" jdbcUrl = "jdbc:postgresql://localhost:5432/my_db" username = "user" password = "password" maximumPoolSize = 10 isAutoCommit = false }
val dataSource = HikariDataSource(config) Database.connect(dataSource) }}1.3. تعريف الجداول وعمليات CRUD
يستخدم Exposed أسلوب DSL لوصف الجداول. لنقم بتعريف جدول بسيط للمستخدمين:
import org.jetbrains.exposed.sql.Tableimport org.jetbrains.exposed.sql.*import org.jetbrains.exposed.sql.transactions.transaction
object Users : Table() { val id = integer("id").autoIncrement() val name = varchar("name", 100) val email = varchar("email", 255).uniqueIndex()
override val primaryKey = PrimaryKey(id)}
// إدراج البياناتfun insertUser(name: String, email: String) { transaction { Users.insert { it[Users.name] = name it[Users.email] = email } }}
// قراءة جميع المستخدمينfun getAllUsers(): List<ResultRow> { return transaction { Users.selectAll().toList() }}
// تحديث البريد الإلكترونيfun updateUserEmail(id: Int, newEmail: String) { transaction { Users.update({ Users.id eq id }) { it[email] = newEmail } }}
// حذف مستخدمfun deleteUser(id: Int) { transaction { Users.deleteWhere { Users.id eq id } }}1.4. ميزات Exposed
- المعاملات (Transactions): يتم تنفيذ جميع العمليات داخل كتلة
transaction. - أمان الأنواع: يتم اكتشاف الأخطاء في استعلامات SQL في مرحلة الترجمة.
- الترحيلات (Migrations): يدعم Exposed الإنشاء التلقائي للجداول عبر
SchemaUtils.create(Users).
2. العمل مع MongoDB عبر KMongo
2.1. إعداد التبعيات
أضف إلى build.gradle.kts:
dependencies { implementation("org.litote.kmongo:kmongo-coroutine:4.9.0") implementation("org.litote.kmongo:kmongo-id:4.9.0")}<