הגדרה של קשרי גומלין מסוג אחד-לרבים ושליחת שאילתות לגביהם

קשר גומלין מסוג אחד-לרבים בין שתי ישויות הוא קשר שבו כל מופע של ישות האב מתאים לאפס או יותר מופעים של ישות הצאצא, אבל כל מופע של ישות הצאצא יכול להתאים רק למופע אחד של ישות האב.

בדוגמה של אפליקציית סטרימינג של מוזיקה, נניח שהמשתמש יכול לארגן את השירים שלו בפלייליסטים. כל משתמש יכול ליצור כמה פלייליסטים שהוא רוצה, אבל כל פלייליסט נוצר על ידי משתמש אחד בלבד. לכן, יש קשר של אחד לרבים בין הישות User לישות Playlist.

כדי להגדיר שאילתות של קשרים מסוג אחד לרבים במסד הנתונים:

  1. הגדרת הקשר: יוצרים מחלקות לשני הישויות, כאשר ישות הצאצא מפנה למפתח הראשי של ישות האב.
  2. שליחת שאילתות לגבי הישויות: יוצרים מודל של הקשר במחלקת נתונים חדשה ומטמיעים פונקציה לאחזור הנתונים שקשורים לישויות.

הגדרת הקשר

כדי להגדיר קשר של אחד לרבים, צריך קודם ליצור מחלקה לכל ישות. בדומה לקשר גומלין מסוג אחד לאחד, יש לכלול בישות הצאצא משתנה שמפנה למפתח הראשי של ישות אם.

@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>
)