علاقة رأس بأطراف بين كيانين هي علاقة يرتبط فيها كل مثيل من الكيان الرئيسي بصفر أو أكثر من مثيلات الكيان التابع، ولكن يمكن أن يرتبط كل مثيل من الكيان التابع بمثيل واحد فقط من الكيان الرئيسي.
في مثال تطبيق بث الموسيقى، لنفترض أنّ المستخدم يمكنه تنظيم أغانيه في قوائم تشغيل. يمكن لكل مستخدم إنشاء العدد الذي يريده من قوائم التشغيل،
ولكن يمكن لمستخدم واحد فقط إنشاء كل قائمة تشغيل. لذلك، هناك علاقة رأس بأطراف بين الكيان User والكيان Playlist.
اتّبِع الخطوات التالية لتحديد علاقات "واحد إلى متعدد" والاستعلام عنها في قاعدة البيانات:
- تحديد العلاقة: أنشئ فئات لكل من الكيانين، مع الإشارة إلى المفتاح الأساسي للعنصر الأصل في العنصر التابع.
- طلب البحث عن الكيانات: صمِّم العلاقة في فئة بيانات جديدة ونفِّذ دالة لاسترداد البيانات ذات الصلة.
تحديد العلاقة
لتحديد علاقة بين عنصر واحد وعدة عناصر، عليك أولاً إنشاء فئة لكل كيان. كما هو الحال في العلاقة بين عنصرين، يجب أن يتضمّن العنصر التابع متغيّرًا يشير إلى المفتاح الأساسي للعنصر الرئيسي.
@Entity data class User( @PrimaryKey val userId: Long, val name: String, val age: Int ) @Entity data class Playlist( @PrimaryKey val playlistId: Long, val userCreatorId: Long, val playlistName: String )
طلب البحث عن الكيانات
للاستعلام عن قائمة المستخدمين وقوائم التشغيل المقابلة، عليك أولاً تصميم العلاقة بين الكيانين من النوع "واحد إلى متعدد".
لنمذجة العلاقة، أنشئ فئة بيانات جديدة. يحتوي كل مثيل من هذه الفئة على مثيل من الكيان الأصل وقائمة بجميع مثيلات الكيان الفرعي ذات الصلة.
أضِف التعليق التوضيحي @Relation إلى السمة التي تمثّل قائمة الكيانات الفرعية. اضبط parentColumns على اسم عمود المفتاح الأساسي للعنصر الرئيسي، واضبط entityColumns على اسم عمود العنصر التابع الذي يشير إلى المفتاح الأساسي للعنصر الرئيسي.
data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["userId"], entityColumns = ["userCreatorId"] ) val playlists: List<Playlist> )
أخيرًا، أضِف دالة إلى فئة كائن الوصول إلى البيانات (DAO) تعرض جميع مثيلات فئة البيانات التي تربط الكيان الرئيسي بالكيان الفرعي.
أضِف التعليق التوضيحي @Transaction لكي تنفّذ Room العملية بأكملها بشكل ذري. هذا التعليق التوضيحي ضروري لأنّ الدالة تتطلّب أن ينفّذ Room طلبَي بحث.
@Transaction @Query("SELECT * FROM User") suspend fun getUsersWithPlaylists(): List<UserWithPlaylists>
المفاتيح المركّبة
إذا حدّدت العلاقة باستخدام مفاتيح مركّبة، حدِّد أعمدة متعدّدة في
parentColumns وentityColumns. يجب أن يتطابق ترتيب الأعمدة في parentColumns مع ترتيب الأعمدة في entityColumns.
@Entity(primaryKeys = ["firstName", "lastName"]) data class User( val firstName: String, val lastName: String, val age: Int ) @Entity data class Playlist( @PrimaryKey val playlistId: Long, val userFirstName: String, val userLastName: String, val playlistName: String ) data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["firstName", "lastName"], entityColumns = ["userFirstName", "userLastName"] ) val playlists: List<Playlist> )