הגדרה של קשרים אחד לאחד ושליחת שאילתות לגבי קשרים כאלה

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

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

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

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

הגדרת הקשר

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

@Entity
data class User(
    @PrimaryKey val userId: Long,
    val name: String,
    val age: Int
)

@Entity
data class Library(
    @PrimaryKey val libraryId: Long,
    val userOwnerId: Long
)

שאילתת הישויות

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

כדי ליצור מודל של הקשר, יוצרים מחלקת נתונים חדשה שבה כל מופע מכיל מופע של ישות אם וישות הצאצא התואמת. מוסיפים את ההערה @Relation לישות הצאצא. מגדירים את parentColumns לשם של עמודת המפתח הראשי של ישות האב, ואת entityColumns לשם של העמודה של ישות הבן שמפנה למפתח הראשי של ישות האב.

data class UserAndLibrary(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["userId"],
        entityColumns = ["userOwnerId"]
    )
    val library: Library
)

לבסוף, מוסיפים פונקציה למחלקה של אובייקט הגישה לנתונים (DAO) שמחזירה את כל המקרים של מחלקת הנתונים שמקשרת בין ישות האם לישות הבן. מוסיפים את ההערה @Transaction כדי לוודא ש-Room מבצע את כל הפעולה באופן אטומי, כי הפונקציה הזו דורשת מ-Room להריץ שתי שאילתות.

@Transaction
@Query("SELECT * FROM User")
suspend fun getUsersAndLibraries(): List<UserAndLibrary>

מפתחות מורכבים

אם מגדירים את הקשר באמצעות מפתחות מורכבים, מציינים כמה עמודות ב-parentColumns וב-entityColumns. הסדר של העמודות ב-parentColumns צריך להיות זהה לסדר של העמודות ב-entityColumns.

@Entity(primaryKeys = ["firstName", "lastName"])
data class User(
    val firstName: String,
    val lastName: String,
    val age: Int
)

@Entity
data class Library(
    @PrimaryKey val libraryId: Long,
    val userFirstName: String,
    val userLastName: String
)

data class UserAndLibrary(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["firstName", "lastName"],
        entityColumns = ["userFirstName", "userLastName"]
    )
    val library: Library
)