الإصدار 3.0 من مكتبة Room
| آخر خبر | الإصدار المستقر | إصدار محتمل | الإصدار التجريبي | الإصدار الأولي |
|---|---|---|---|---|
| 2026-05-06 | - | - | - | 3.0.0-alpha04 |
تحديد الاعتماديات
لإضافة اعتمادية على Room3، يجب تضمين مستودع Google Maven في مشروعك. اطّلِع على مستودع Maven من Google لمزيد من المعلومات.
أضِف الاعتماديات الخاصة بالعناصر التي تحتاج إليها في ملف build.gradle لتطبيقك أو وحدتك:
Kotlin
dependencies { val room_version = "" implementation("androidx.room3:room3-runtime:$room_version") ksp("androidx.room3:room3-compiler:$room_version") }
أنيق
dependencies { def room_version = "" implementation "androidx.room3:room3-runtime:$room_version" ksp "androidx.room3:room3-compiler:$room_version" }
للحصول على معلومات حول استخدام المكوّن الإضافي KSP، يُرجى الاطّلاع على مستندات البدء السريع في KSP.
لمزيد من المعلومات حول الاعتماديات، يُرجى الاطّلاع على مقالة إضافة اعتماديات الإصدار.
استخدام المكوّن الإضافي Room Gradle
يمكنك استخدام المكوّن الإضافي Room Gradle لضبط خيارات برنامج Room البرمجي المترجم. يضبط المكوّن الإضافي المشروع بحيث يتم ضبط المخططات التي يتم إنشاؤها (وهي ناتج مهام التجميع ويتم استخدامها لعمليات النقل التلقائي) بشكلٍ صحيح للحصول على عمليات إنشاء قابلة للتكرار والتخزين المؤقت.
لإضافة المكوّن الإضافي، حدِّد المكوّن الإضافي وإصداره في ملف إنشاء Gradle على المستوى الأعلى.
أنيق
plugins { id 'androidx.room3' version "$room_version" apply false }
Kotlin
plugins { id("androidx.room3") version "$room_version" apply false }
في ملف إنشاء Gradle على مستوى الوحدة، طبِّق المكوّن الإضافي واستخدِم الإضافة room3.
أنيق
plugins { id 'androidx.room3' } room3 { schemaDirectory "$projectDir/schemas" }
Kotlin
plugins { id("androidx.room3") } room3 { schemaDirectory("$projectDir/schemas") }
يجب ضبط schemaDirectory عند استخدام المكوّن الإضافي Room Gradle. سيؤدي ذلك إلى ضبط برنامج Room البرمجي المترجم ومهام التجميع المختلفة والواجهات الخلفية (kotlinc وKSP) لإنشاء ملفات المخططات في مجلدات النكهات، مثلاً schemas/flavorOneDebug/com.package.MyDatabase/1.json. يجب تسجيل هذه الملفات في المستودع لاستخدامها في عمليات التحقق من الصحة وعمليات النقل التلقائي.
الملاحظات
تساعدنا ملاحظاتك في تحسين Jetpack. يُرجى إعلامنا إذا اكتشفت مشاكل جديدة أو كانت لديك أفكار لتحسين هذه المكتبة. يُرجى الاطّلاع على الـ مشاكل الحالية في هذه المكتبة قبل إنشاء مشكلة جديدة. يمكنك إضافة صوتك إلى مشكلة حالية من خلال النقر على زر النجمة.
يُرجى الاطّلاع على مستندات أداة تتبُّع المشاكل لمزيد من المعلومات.
الإصدار 3.0
الإصدار 3.0.0-alpha04
2026-05-06
تم طرح androidx.room3:room3-*:3.0.0-alpha04. يتضمّن الإصدار 3.0.0-alpha04 هذه التعديلات.
التغييرات في واجهة برمجة التطبيقات
- تمت إضافة واجهات برمجة تطبيقات لضبط مجموعة اتصالات Room. يمكن استخدام دالتَي الإنشاء
setSingleConnectionPool()وsetMultipleConnectionPool()للتحكّم في الحد الأقصى لعدد الاتصالات التي سيفتحها Room بقاعدة البيانات. (I9700d, b/438041176, b/432820350) - تمت إزالة
DatabaseConfigurationمن Room من واجهة برمجة التطبيقات العامة لأنّه لم تتم الإشارة إلى الإعدادات من خلال أي واجهة برمجة تطبيقات عامة أخرى. (I5f1e9, b/438041176)
الإصدار 3.0.0-alpha03
2026-04-08
تم طرح androidx.room3:room3-*:3.0.0-alpha03. يتضمّن الإصدار 3.0.0-alpha03 هذه التعديلات.
التغييرات في واجهة برمجة التطبيقات
- تمت إتاحة الدالة الإنشائية بدون وسيطات في
RoomDatabaseللجميع لتجنُّب ظهور تحذير من أداة Lint عند الإشارة إلى الدالة الإنشائية في بيان ` @Database`. (I9bac2, b/494722261) - تمت إضافة إصدار من
Room.inMemoryDatabaseBuilderوRoom.databaseBuilderلا يتضمّن `Context` من Android. تم تقليل الحاجة إلى `Context` بشكلٍ كبير في Room 3.0، وبالتالي فإنّ جعلها قيمة اختيارية لـ `Builder` يسمح بإنشاء قواعد بيانات في الذاكرة في الرمز الشائع بسهولة أكبر. (I5d502, b/438041176)
إصلاح الأخطاء
- تم إصلاح الخطأ "الرمز كبير جدًا" في الرمز الذي تم إنشاؤه على JVM وAndroid عندما كان نص الدالة
onValidateSchemaكبيرًا جدًا (b/493708172).
الإصدار 3.0.0-alpha02
2026-03-25
تم طرح androidx.room3:room3-*:3.0.0-alpha02. يتضمّن الإصدار 3.0.0-alpha02 هذه التعديلات.
الميزات الجديدة
- إتاحة FTS5: تمت إضافة إتاحة FTS5 إلى Room من خلال التعليق التوضيحي
@Fts5. ويشمل ذلك ثوابت جديدة لمحلّلات FTS5 (TOKENIZER_ASCIIوTOKENIZER_TRIGRAM) وتعدادًا لخيار FTS "التفاصيل" (FULLوCOLUMNوNONE). (I90934، b/146824830) - أهداف ترقيم الصفحات في Room: تمت إضافة أهداف
jsوwasmJsوtvOSوwatchOSإلىroom3-paging. (Icffd3, b/432783733)
التغييرات في واجهة برمجة التطبيقات
- الدالة المتعددة المنصات
clearAllTables(): تم توحيد الدالةclearAllTables()، ما يجعلها متاحة على جميع المنصات. تم أيضًا تحويلها إلى دالةsuspend. (I434ae, b/322846465) - عملية النقل المدمّرة: تمت إضافة قيمة مَعلمة تلقائية إلى
dropAllTablesفي واجهات برمجة التطبيقاتfallbackToDestructiveMigration. (Ica88b, b/438041176) التغييرات في واجهة برمجة التطبيقات التجريبية:
تم نقل
@ExperimentalRoomApiإلىroom-commonللسماح بوضع علامة "تجريبي" على واجهات برمجة التطبيقات المستندة إلى التعليقات التوضيحية.تمت إضافة
RoomWarningتجريبي لإزالة شرط@ConstructedByفي بيان قاعدة بيانات Room. في هذه الحالة، لن يتم إنشاءDatabaseConstructor، ويجب توفير عملية تنفيذ المصنع من خلالDatabaseBuilder. (If5443)
إصلاح الأخطاء
- مصدر ترقيم الصفحات: تم تعديل
PagingSourceDaoReturnTypeConverterللإشارة بشكلٍ صحيح إلى أنّ دالة التحويل مخصّصة لطلبات READ. (I3b067, b/139872302)
الإصدار 3.0.0-alpha01
2026-03-11
تم طرح androidx.room3:room3-*:3.0.0-alpha01.
الإصدار 3.0 من Room (الحزمة androidx.room3) هو تحديث رقم الإصدار الرئيسي للإصدار من حزمة Room 2.x (androidx.room) يركّز على Kotlin Multiplatform (KMP).
تظل واجهات برمجة التطبيقات الأساسية للتعليقات التوضيحية كما هي إلى جانب المكوّنات الرئيسية:
- الفئة المجرّدة التي توسّع
androidx.room3.RoomDatabaseوالتي تم وضع التعليق التوضيحي@Databaseعليها هي نقطة الدخول إلى معالج التعليقات التوضيحية في Room. - يحتوي بيان قاعدة البيانات على فئة بيانات واحدة أو أكثر تصف مخطط قاعدة البيانات وتم وضع التعليق التوضيحي
@Entityعليها. - يتم تحديد عمليات قاعدة البيانات في بيانات
@Daoالتي تحتوي على دوال طلب بحث يتم تحديد عبارات SQL الخاصة بها من خلال التعليق التوضيحي@Query. - في وقت التشغيل، يمكن الحصول على عملية تنفيذ قاعدة البيانات من خلال
RoomDatabase.Builderالذي يُستخدم أيضًا لضبط قاعدة البيانات.
لا يزال معظم المحتوى في دليل حفظ البيانات في قاعدة بيانات محلية باستخدام Room مناسبًا للإصدار 3.0 من Room.
في ما يلي الاختلافات الرئيسية التي تؤدي إلى حدوث مشاكل في التوافق بين الإصدار 3.0 من Room والإصدار 2.x:
- حزمة جديدة،
androidx.room3 - لم تعُد واجهات برمجة تطبيقات SupportSQLite متوافقة، إلا إذا كنت تستخدم
androidx.room3:room3-sqlite-wrapper. - تستند جميع عمليات قاعدة البيانات الآن إلى واجهات برمجة تطبيقات Coroutine.
- لا يتم إنشاء سوى رمز Kotlin.
- يجب استخدام Kotlin Symbol Processing (KSP).
بالإضافة إلى التغييرات التي تؤدي إلى حدوث مشاكل في التوافق، يقدّم الإصدار 3.0 من Room وظائف جديدة مقارنةً بالإصدار 2.x:
- إتاحة JS وWasmJS
- أنواع الإرجاع المخصّصة لـ DAO
حزمة جديدة
لتجنُّب مشاكل التوافق مع عمليات تنفيذ Room 2.x الحالية والمكتبات التي تحتوي على تبعيات متعدية على Room (مثل WorkManager)، يقع الإصدار 3.0 من Room في حزمة جديدة، ما يعني أنّه يحتوي أيضًا على معرّفات عناصر ومعرّفات مجموعة Maven جديدة. على سبيل المثال، أصبح androidx.room:room-runtime هو androidx.room3:room3-runtime، وستكون الفئات مثل androidx.room.RoomDatabase موجودة الآن في androidx.room3.RoomDatabase.
لا تتوفّر واجهات برمجة تطبيقات SupportSQLite
يستند الإصدار 3.0 من Room بالكامل إلى واجهات برمجة تطبيقات SQLiteDriver
ولم يعُد يشير إلى أنواع SupportSQLite مثل SupportSQLiteDatabase
أو أنواع Android مثل Cursor. هذا هو التغيير الأهم بين الإصدار 3.0 من Room والإصدار 2.x، لأنّه تمت إزالة واجهات برمجة تطبيقات RoomDatabase التي كانت تعكس SupportSQLiteDatabase إلى جانب واجهة برمجة التطبيقات للحصول على SupportSQLiteOpenHelper. يجب الآن توفّر SQLiteDriver لإنشاء RoomDatabase.
على سبيل المثال، تم استبدال واجهات برمجة التطبيقات لعمليات قاعدة البيانات المباشرة بما يعادلها من واجهات برمجة تطبيقات برنامج التشغيل:
// Room 2.x
roomDatabase.runInTransaction { ... }
// Room 3.x
roomDatabase.withWriteTransaction { ... }
// Room 2.x
roomDatabase.query("SELECT * FROM Song").use { cursor -> ... }
// Room 3.x
roomDatabase.useReaderConnection { connection ->
connection.usePrepared("SELECT * FROM Song") { stmt -> ... }
}
تم أيضًا استبدال واجهات برمجة تطبيقات معاودة الاتصال التي كانت تتضمّن SupportSQLiteDatabase كإحدى الوسيطات بواجهة برمجة التطبيقات المكافئة التي تتضمّن SQLiteConnection كإحدى الوسيطات.
وهذه هي دوال معاودة الاتصال لعمليات النقل مثل Migration.onMigrate() وAutoMigrationSpec.onPostMigrate() إلى جانب معاودات الاتصال بقاعدة البيانات مثل RoomDatabase.Callback.onCreate() وRoomDatabase.Callback.onOpen() وما إلى ذلك.
إذا كان يتم استخدام Room في مشروع KMP، يصبح النقل إلى الإصدار 3.0 هو الأبسط لأنّه يتضمّن في الغالب تعديل مراجع الاستيراد، وإلا فإنّ استراتيجية النقل نفسها من Room في Android فقط إلى KMP تنطبق، يُرجى الاطّلاع على دليل نقل بيانات Room إلى KMP.
برنامج تضمين SupportSQLite
يحافظ الإصدار 3.x من Room على برنامج تضمين SupportSQLite الذي تم إنشاؤه في الإصدار 2.x لتسهيل عمليات النقل، ويقع الآن في عنصر جديد androidx.room3:room3-sqlite-wrapper. تتيح لك واجهة برمجة التطبيقات المتوافقة تحويل RoomDatabase إلى SupportSQLiteDatabase. يمكن استبدال طلبات roomDatabase.openHelper.writableDatabase بـ roomDatabase.getSupportWrapper().
الأولوية للغة Kotlin والكوروتينات
لتطوير المكتبة بشكلٍ أفضل، لا ينشئ الإصدار 3.0 من Room سوى رمز Kotlin وهو معالج رموز Kotlin (KSP) فقط. مقارنةً بالإصدار 2.x من Room، لا يتم إنشاء رمز Java، ولم يعُد من الممكن ضبط معالج التعليقات التوضيحية من خلال KAPT أو JavaAP في الإصدار 3.0 من Room. يُرجى العِلم أنّ KSP يمكنه معالجة مصادر Java، وسينشئ برنامج Room البرمجي المترجم رمزًا لقاعدة البيانات أو الكيانات أو كائنات DAO التي تكون بياناتها المصدرية في Java. يُنصح باستخدام مشروع متعدد الوحدات حيث يتركز استخدام Room ويمكن تطبيق المكوّن الإضافي Kotlin Gradle وKSP بدون التأثير في بقية قاعدة الرموز البرمجية.
يتطلب الإصدار 3.0 من Room أيضًا استخدام الكوروتينات، وبشكلٍ أكثر تحديدًا، يجب أن تكون دوال DAO معلّقة ما لم تكن تعرض نوعًا تفاعليًا، مثل Flow أو نوع القيمة التي تم إرجاعها مخصّص لـ DAO. واجهات برمجة تطبيقات Room لتنفيذ عمليات قاعدة البيانات هي أيضًا دوال تعليق، مثل RoomDatabase.useReaderConnection وRoomDatabase.useWriterConnection.
على عكس الإصدار 2.x من Room، لم يعُد من الممكن ضبط RoomDatabase باستخدام Executor، بدلاً من ذلك، يمكن توفير CoroutineContext إلى جانب برنامج الإرسال من خلال أداة إنشاء قاعدة البيانات.
تستند واجهات برمجة تطبيقات InvalidationTracker في الإصدار 3.0 من Room إلى Flow، وتمت إزالة InvalidationTracker.Observer إلى جانب واجهات برمجة التطبيقات ذات الصلة addObserver و removeObserver. آلية التفاعل مع عملية قاعدة البيانات هي من خلال Coroutine Flows التي يمكن إنشاؤها من خلال واجهة برمجة التطبيقات createFlow() في InvalidationTracker.
مثال على الاستخدام:
fun getArtistTours(from: Date, to: Date): Flow<Map<Artist, TourState>> {
return db.invalidationTracker.createFlow("Artist").map { _ ->
val artists = artistsDao.getAllArtists()
val tours = tourService.fetchStates(artists.map { it.id })
associateTours(artists, tours, from, to)
}
}
إتاحة الويب
يضيف الإصدار 3.0 من Room JavaScript وWasmJs كأهداف KMP. بالإضافة إلى
طرح واجهات SQLiteDriver (androidx.sqlite:sqlite) التي
تستهدف أيضًا JavaScript وWasmJs وبرنامج تشغيل جديد WebWorkerSQLiteDriver
موجود في العنصر الجديد androidx.sqlite:sqlite-web، من الممكن استخدام
Room في الرمز الشائع الذي يستهدف جميع منصات KMP الرئيسية.
نظرًا إلى طبيعة منصات الويب غير المتزامنة، أصبحت واجهات برمجة تطبيقات Room التي كانت تتضمّن SQLiteStatement كإحدى الوسيطات دوال تعليق. من أمثلة هذه الدوال Migration.onMigrate() وRoomDatabase.Callback.onCreate() وPooledConnection.usePrepared() وغيرها. في واجهات برمجة تطبيقات برنامج التشغيل، تكون واجهات برمجة التطبيقات غير المتزامنة شائعة على جميع المنصات، وتكون واجهات برمجة التطبيقات المتزامنة شائعة للأهداف غير المتوافقة مع الويب. لذلك، يمكن لمشروع لا يستهدف الويب مواصلة استخدام واجهات برمجة التطبيقات المتزامنة (SQLiteDriver.open() وSQLiteConnection.prepare() وSQLiteStatement.step()) في الرمز الشائع.
في المقابل، يجب أن يستخدم المشروع الذي يستهدف الويب فقط واجهات برمجة التطبيقات غير المتزامنة (SQLiteDriver.openAsync() وSQLiteConnection.prepareAsync() وSQLiteStatement.stepAsync()).
لتسهيل الأمر، أضافت حزمة androidx.sqlite أيضًا دوال الإضافة المعلقة بأسماء متزامنة لواجهات برمجة التطبيقات المذكورة (مع إضافة SQLiteConnection.executeSQL)، ويُنصح باستخدام واجهات برمجة التطبيقات هذه عندما يستهدف المشروع كلاً من منصات الويب وغير الويب، لأنّ واجهات برمجة التطبيقات هي بيانات متوقّعة / فعلية ستستدعي المتغيّر الصحيح استنادًا إلى المنصات. هذه هي واجهات برمجة التطبيقات التي يستخدمها وقت تشغيل Room وتتيح استخدام برنامج التشغيل في الرمز الشائع لجميع المنصات المتوافقة.
مثال على الاستخدام:
import androidx.sqlite.executeSQL
import androidx.sqlite.step
roomDatabase.useWriterConnection { connection ->
val deletedSongs = connection.usePrepared(
"SELECT count(*) FROM Song"
) { stmt ->
stmt.step()
stmt.getLong(0)
}
connection.executeSQL("DELETE FROM Song")
deletedSongs
}
WebWorkerSQLiteDriver هو عملية تنفيذ SQLiteDriver تتواصل مع Web Worker لتنفيذ عملية قاعدة البيانات خارج سلسلة التعليمات الرئيسية وتتيح تخزين قاعدة البيانات في نظام الملفات الخاص بالمصدر (OPFS). لإنشاء برنامج التشغيل
يجب توفّر عامل ينفّذ بروتوكول اتصال بسيط، ويتم وصف
البروتوكول في WebWorkerSQLiteDriver
KDoc.
لا يتضمّن WebWorkerSQLiteDriver حاليًا عاملاً تلقائيًا ينفّذ بروتوكول الاتصال، ولكن على سبيل المثال، تحتوي قاعدة رموز androidx البرمجية على عملية تنفيذ عامل يمكن استخدامها في مشروعك. يستخدم هذا العامل WASM من
SQLite's
ويخزّن قاعدة البيانات في OPFS. يتم نشر العامل النموذجي كحزمة NPM محلية، وبفضل
إتاحة Kotlin لتبعيات NPM،
يمكن إنشاء وحدة KMP صغيرة لخدمة العامل.
يُرجى الاطّلاع على مشروع GitHub التالي الذي يوضّح استخدام عامل ويب محلي لـ Room.
بعد إعداد عامل في المشروع، يكون ضبط Room للويب مشابهًا للمنصات الأخرى:
fun createDatabase(): MusicDatabase {
return Room.databaseBuilder<MusicDatabase>("music.db")
.setDriver(WebWorkerSQLiteDriver(createWorker()))
.build()
}
fun createWorker() =
Worker(js("""new URL("sqlite-web-worker/worker.js", import.meta.url)"""))
قد يحتوي إصدار مستقبلي من برنامج تشغيل الويب على عامل تلقائي تم نشره في NPM، ما يسهّل عملية الإعداد على الويب.
أنواع الإرجاع المخصّصة لـ DAO
تم تحويل عمليات دمج أنواع القيمة التي تم إرجاعها المختلفة لـ DAO، مثل عمليات دمج RxJava وPaging، لاستخدام واجهة برمجة تطبيقات جديدة في الإصدار 3.0 من Room تُسمى محوّلات نوع القيمة التي تم إرجاعها لـ DAO.
تتيح دالة محوّل نوع القيمة التي تم إرجاعها لـ DAO (@DaoReturnTypeConverter) تحويل نتيجة دالة DAO إلى نوع مخصّص محدّد من خلال الدالة التي تم وضع التعليق التوضيحي عليها. تتيح هذه الدوال المشاركة في الرمز الذي تم إنشاؤه في Room والذي يحوّل نتائج طلب البحث إلى عناصر بيانات. يجب تسجيل الفئات التي تحتوي على محوّلات نوع القيمة التي تم إرجاعها لـ DAO من خلال التعليقات التوضيحية @DaoReturnTypeConverters في بيانات @Database أو @Dao.
على سبيل المثال، لكي يعرض طلب بحث DAO PagingSource، يجب الآن تسجيل فئة المحوّل الموجودة في androidx.room3:room3-paging:
@Dao
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
interface MusicDao {
@Query("SELECT * FROM Song)
fun getSongsPaginated(): PagingSource<Int, Song>
}
تم نقل عمليات الدمج الحالية إلى محوّلات نوع القيمة التي تم إرجاعها لـ DAO:
| نوع القيمة التي يتم عرضها | فئة المحوّل | العنصر |
|---|---|---|
| PagingSource | PagingSourceDaoReturnTypeConverter | androidx.room3:room3-paging |
| Observable وFlowable وCompletable وSingle وMaybe | RxDaoReturnTypeConverters | androidx.room3:room3-rxjava3 |
| ListenableFuture | GuavaDaoReturnTypeConverter | androidx.room3:room3-guava |
| LiveData | LiveDataDaoReturnTypeConverter | androidx.room3:room3-livedata |
على غرار محوّلات نوع العمود، يمكن للتطبيق تحديد محوّلات نوع القيمة التي تم إرجاعها لـ DAO. على سبيل المثال، يمكن لتطبيق بيان @DaoReturnTypeConverter لنوع الويب kotlin.js.Promise.
object PromiseDaoReturnTypeConverter {
@DaoReturnTypeConverter([OperationType.READ, OperationType.WRITE])
fun <T> convert(
db: RoomDatabase,
executeAndConvert: suspend () -> T
): Promise<T> {
return db.getCoroutineScope().promise { executeAndConvert() }
}
}
يسمح المحوّل أعلاه بعد ذلك لدوال طلب بحث DAO بعرض Promise:
@Dao
@DaoReturnTypeConverters(PromiseDaoReturnTypeConverter::class)
interface MusicDao {
@Query("SELECT * FROM Song")
fun getAllSongs(): Promise<List<Song>>
}
تتضمّن دالة @DaoReturnTypeConverter بعض المتطلبات من حيث عدد المَعلمات التي يجب أن تحتوي عليها وأنواعها. في ما يلي المَعلمات المحتملة:
db: RoomDatabase: (اختياري) يوفّر إمكانية الوصول إلىRoomDatabaseالمثيل، ما قد يكون مفيدًا لتنفيذ عمليات قاعدة بيانات إضافية أو الوصول إلى نطاق الكوروتين.tableNames: Array<String>: (اختياري) يحتوي على الجداول التي تم الوصول إليها في طلب البحث، ما يكون مفيدًا لإتاحة الأنواع القابلة للملاحظة / التفاعلية عند دمجها مع واجهة برمجة التطبيقاتInvalidationTracker.createFlow()في Room.rawQuery: RoomRawQuery: (اختياري) يحتوي في وقت التشغيل على مثيل لطلب البحث، ما يتيح إجراء عمليات التحويل مثل استراتيجيةLIMIT/OFFSETالتي تنفّذهاPagingSourceDaoReturnTypeConverter.executeAndConvert: suspend () -> T: (مطلوب) الدالة التي تم إنشاؤها في Room والتي ستنفّذ طلب البحث وتحلّل نتيجته إلى عناصر بيانات.
لمزيد من المعلومات حول متطلبات إنشاء محوّل نوع القيمة التي تم إرجاعها لـ DAO
، يُرجى الاطّلاع على KDoc في واجهة برمجة التطبيقات @DaoReturnTypeConverter.