नेस्ट किए गए संबंधों को तय करना और उनसे जुड़ी क्वेरी करना

कभी-कभी आपको तीन या उससे ज़्यादा टेबल के सेट की क्वेरी करने की ज़रूरत पड़ सकती है. ये सभी टेबल एक-दूसरे से जुड़ी होती हैं. ऐसे में, टेबल के बीच नेस्टेड रिलेशनशिप तय किए जाते हैं.

मान लें कि संगीत स्ट्रीमिंग ऐप्लिकेशन के उदाहरण में, आपको सभी उपयोगकर्ताओं, हर उपयोगकर्ता के लिए सभी प्लेलिस्ट, और हर उपयोगकर्ता के लिए हर प्लेलिस्ट में मौजूद सभी गानों की क्वेरी करनी है. उपयोगकर्ताओं का प्लेलिस्ट के साथ वन-टू-मेनी रिलेशनशिप होता है. वहीं, प्लेलिस्ट का गानों के साथ मेनी-टू-मेनी रिलेशनशिप होता है. कोड के इस उदाहरण में, इन एलिमेंट को दिखाने वाली क्लास के साथ-साथ, प्लेलिस्ट और गानों के बीच मेनी-टू-मेनी रिलेशनशिप के लिए क्रॉस-रेफ़रंस टेबल भी दिखाई गई है:

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

@Entity
data class Song(
    @PrimaryKey val songId: Long,
    val songName: String,
    val artist: String
)

@Entity(primaryKeys = ["playlistId", "songId"], indices = [Index("playlistId", "songId")])
data class PlaylistSongCrossRef(
    val playlistId: Long,
    val songId: Long
)

सबसे पहले, अपने सेट में मौजूद दो टेबल के बीच रिलेशनशिप को सामान्य तरीके से मॉडल करें. इसके लिए, डेटा क्लास और @Relation एनोटेशन का इस्तेमाल करें. यहां दिए गए उदाहरण में, PlaylistWithSongs क्लास दिखाई गई है. यह मेनी-टू-मेनी रिलेशनशिप को मॉडल करती है जो Playlist एंटिटी क्लास और Song एंटिटी क्लास के बीच है:

data class PlaylistWithSongs(
    @Embedded val playlist: Playlist,
    @Relation(
        parentColumns = ["playlistId"],
        entityColumns = ["songId"],
        associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val songs: List<Song>
)

इस रिलेशनशिप को दिखाने वाली डेटा क्लास तय करने के बाद, एक और डेटा क्लास बनाएं. यह क्लास, आपके सेट में मौजूद किसी दूसरी टेबल और पहली रिलेशनशिप क्लास के बीच रिलेशनशिप को मॉडल करती है. साथ ही, नई क्लास में मौजूदा रिलेशनशिप को "नेस्ट" करती है. यहां दिए गए उदाहरण में, UserWithPlaylistsAndSongs क्लास दिखाई गई है. यह User एंटिटी क्लास और PlaylistWithSongs रिलेशनशिप क्लास के बीच वन-टू-मेनी रिलेशनशिप को मॉडल करती है:

data class UserWithPlaylistsAndSongs(
    @Embedded val user: User,
    @Relation(
        entity = Playlist::class,
        parentColumns = ["userId"],
        entityColumns = ["userCreatorId"]
    )
    val playlists: List<PlaylistWithSongs>
)

UserWithPlaylistsAndSongs क्लास, तीनों एंटिटी क्लास के बीच रिलेशनशिप को इनडायरेक्ट तरीके से मॉडल करती है: User, Playlist, और Song. इसे पहली इमेज में दिखाया गया है.

UserWithPlaylistsAndSongs, User और PlaylistWithSongs के बीच के संबंध को मॉडल करता है. वहीं, PlaylistWithSongs, Playlist और Song के बीच के संबंध को मॉडल करता है.
पहली इमेज. संगीत स्ट्रीमिंग ऐप्लिकेशन के उदाहरण में, रिलेशनशिप क्लास का डायग्राम.

अगर आपके सेट में ज़्यादा टेबल हैं, तो हर बची हुई टेबल और पिछली रिलेशनशिप क्लास के बीच रिलेशनशिप को मॉडल करने के लिए, एक क्लास बनाएं. इस प्रोसेस से, क्वेरी करने के लिए चुनी गई सभी टेबल के बीच नेस्टेड रिलेशनशिप की चेन बनती है.

आखिर में, डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) क्लास में एक फ़ंक्शन जोड़ें. इससे, आपके ऐप्लिकेशन के लिए ज़रूरी क्वेरी फ़ंक्शन को दिखाया जा सकेगा. इस फ़ंक्शन के लिए, Room को एक से ज़्यादा क्वेरी चलाने की ज़रूरत होती है. इसलिए, @Transaction एनोटेशन जोड़ें, ताकि पूरी कार्रवाई एटॉमिक तरीके से हो:

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