कई-से-कई रिलेशनशिप तय करना और उनसे जुड़ी क्वेरी करना

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

म्यूज़िक स्ट्रीमिंग ऐप्लिकेशन के उदाहरण में, उपयोगकर्ता की तय की गई प्लेलिस्ट में मौजूद गानों पर विचार करें. हर प्लेलिस्ट में कई गाने शामिल हो सकते हैं. साथ ही, हर गाना कई अलग-अलग प्लेलिस्ट का हिस्सा हो सकता है. इसलिए, Playlist एंटिटी और Song एंटिटी के बीच मेनी-टू-मेनी रिलेशनशिप होता है.

अपने डेटाबेस में मेनी-टू-मेनी रिलेशनशिप तय करने और उनकी क्वेरी करने के लिए, यह तरीका अपनाएं:

  1. रिलेशनशिप तय करना: मेनी-टू-मेनी रिलेशनशिप दिखाने के लिए, एंटिटी और असोसिएटिव एंटिटी (क्रॉस-रेफ़रंस टेबल) तय करें.
  2. एंटिटी की क्वेरी करना: तय करें कि आपको संबंधित एंटिटी की क्वेरी कैसे करनी है. साथ ही, मनचाहा आउटपुट दिखाने के लिए, डेटा क्लास बनाएं.

रिलेशनशिप तय करना

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

Kotlin

@Entity
data class Playlist(
    @PrimaryKey val playlistId: Long,
    val playlistName: String
)

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

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

Java

@Entity
public class Playlist {
    @PrimaryKey public long playlistId;
    public String playlistName;
}

@Entity
public class Song {
    @PrimaryKey public long songId;
    public String songName;
    public String artist;
}

@Entity(primaryKeys = {"playlistId", "songId"})
public class PlaylistSongCrossRef {
    public long playlistId;
    public long songId;
}

एंटिटी की क्वेरी करना

अगला चरण इस बात पर निर्भर करता है कि आपको इन संबंधित एंटिटी की क्वेरी कैसे करनी है.

  • अगर आपको प्लेलिस्ट और हर प्लेलिस्ट के लिए, उससे जुड़े गानों की सूची की क्वेरी करनी है, तो एक नई डेटा क्लास बनाएं. इसमें एक Playlist ऑब्जेक्ट और Song के उन सभी ऑब्जेक्ट की सूची शामिल होनी चाहिए जो प्लेलिस्ट में शामिल हैं.
  • अगर आपको गानों और हर गाने के लिए, उससे जुड़ी प्लेलिस्ट की सूची की क्वेरी करनी है, तो एक नई डेटा क्लास बनाएं. इसमें एक Song ऑब्जेक्ट और Playlist के उन सभी ऑब्जेक्ट की सूची शामिल होनी चाहिए जिनमें वह गाना शामिल है.

दोनों ही मामलों में, एंटिटी के बीच रिलेशनशिप दिखाने वाली क्रॉस-रेफ़रंस एंटिटी की पहचान करने के लिए, इन दोनों क्लास में @Relation एनोटेशन में associateBy प्रॉपर्टी का इस्तेमाल करके, एंटिटी के बीच रिलेशनशिप को मॉडल करें.PlaylistSong

Kotlin

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

data class SongWithPlaylists(
    @Embedded val song: Song,
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val playlists: List<Playlist>
)

Java

public class PlaylistWithSongs {
    @Embedded public Playlist playlist;
    @Relation(
         parentColumn = "playlistId",
         entityColumn = "songId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Song> songs;
}

public class SongWithPlaylists {
    @Embedded public Song song;
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Playlist> playlists;
}

इसके बाद, डीएओ क्लास में एक ऐसा तरीका जोड़ें जिससे आपके ऐप्लिकेशन को ज़रूरी क्वेरी फ़ंक्शन मिल सके.

  • getPlaylistsWithSongs: यह तरीका, डेटाबेस की क्वेरी करता है और क्वेरी के नतीजे के तौर पर मिले सभी PlaylistWithSongs ऑब्जेक्ट दिखाता है.
  • getSongsWithPlaylists: यह तरीका, डेटाबेस की क्वेरी करता है और क्वेरी के नतीजे के तौर पर मिले सभी SongWithPlaylists ऑब्जेक्ट दिखाता है.

इन तरीकों में से हर एक के लिए, रूम को दो क्वेरी चलाने की ज़रूरत होती है. इसलिए, दोनों तरीकों में @Transaction एनोटेशन जोड़ें, ताकि पूरा ऑपरेशन एटॉमिक तरीके से किया जा सके.

Kotlin

@Transaction
@Query("SELECT * FROM Playlist")
fun getPlaylistsWithSongs(): List<PlaylistWithSongs>

@Transaction
@Query("SELECT * FROM Song")
fun getSongsWithPlaylists(): List<SongWithPlaylists>

Java

@Transaction
@Query("SELECT * FROM Playlist")
public List<PlaylistWithSongs> getPlaylistsWithSongs();

@Transaction
@Query("SELECT * FROM Song")
public List<SongWithPlaylists> getSongsWithPlaylists();