رابطه چند به چند بین دو موجودیت، رابطهای است که در آن هر نمونه از موجودیت والد با صفر یا چند نمونه از موجودیت فرزند متناظر است و عکس این قضیه نیز صادق است.
در مثال برنامه پخش موسیقی، آهنگهای موجود در لیستهای پخش تعریفشده توسط کاربر را در نظر بگیرید. هر لیست پخش میتواند شامل چندین آهنگ باشد و هر آهنگ میتواند به چندین لیست پخش تعلق داشته باشد. بنابراین، یک رابطه چند به چند بین موجودیتهای Playlist و Song وجود دارد.
برای تعریف و پرس و جو از روابط چند به چند در پایگاه داده خود، این مراحل را دنبال کنید:
- تعریف رابطه : موجودیتها و موجودیت انجمنی یا جدول ارجاع متقابل را برای نمایش رابطه چند به چند ایجاد کنید.
- پرسوجو از موجودیتها : مشخص کنید که چگونه میخواهید موجودیتهای مرتبط را پرسوجو کنید و کلاسهای دادهای برای نمایش خروجی مورد نظر ایجاد کنید.
رابطه را تعریف کنید
برای تعریف یک رابطه چند به چند، ابتدا برای هر یک از دو موجودیت خود یک کلاس ایجاد کنید. روابط چند به چند با سایر انواع روابط متمایز هستند زیرا معمولاً هیچ ارجاعی به موجودیت والد در موجودیت فرزند وجود ندارد. در عوض، یک کلاس سوم برای نمایش یک موجودیت انجمنی یا جدول ارجاع متقابل بین دو موجودیت ایجاد کنید. جدول ارجاع متقابل باید ستونهایی برای کلید اصلی از هر موجودیت در رابطه چند به چند نشان داده شده در جدول داشته باشد. در این مثال، هر ردیف در جدول ارجاع متقابل مربوط به جفت شدن یک نمونه Playlist و یک نمونه Song است که در آن لیست پخش ارجاع شده شامل آهنگ ارجاع شده است.
@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"], indices = [Index("playlistId", "songId")]) data class PlaylistSongCrossRef( val playlistId: Long, val songId: Long )
پرس و جو از موجودیتها
مرحله بعدی بستگی به این دارد که چگونه میخواهید از این موجودیتهای مرتبط پرسوجو کنید.
- اگر میخواهید لیستهای پخش و لیستی از آهنگهای مربوطه برای هر لیست پخش را جستجو کنید، یک کلاس داده جدید ایجاد کنید که شامل یک شیء
Playlistو لیستی از اشیاءSongباشد که لیست پخش شامل آن است. - اگر میخواهید آهنگها و لیستی از لیستهای پخش مربوطه برای هر آهنگ را جستجو کنید، یک کلاس داده جدید ایجاد کنید که شامل یک شیء
Songو لیستی از اشیاءPlaylistکه شامل آهنگ هستند، باشد.
در هر صورت، رابطه بین موجودیتها را با استفاده از ویژگی associateBy در حاشیهنویسی @Relation در هر یک از این کلاسها مدلسازی کنید تا موجودیت ارجاع متقابلی که رابطه بین موجودیت Playlist و موجودیت Song را فراهم میکند، شناسایی شود.
data class PlaylistWithSongs( @Embedded val playlist: Playlist, @Relation( parentColumns = ["playlistId"], entityColumns = ["songId"], associateBy = Junction(PlaylistSongCrossRef::class) ) val songs: List<Song> ) data class SongWithPlaylists( @Embedded val song: Song, @Relation( parentColumns = ["songId"], entityColumns = ["playlistId"], associateBy = Junction(PlaylistSongCrossRef::class) ) val playlists: List<Playlist> )
در نهایت، یک تابع به کلاس شیء دسترسی به داده (DAO) اضافه کنید تا تابع پرسوجوی مورد نیاز برنامه شما را نمایش دهد.
-
getPlaylistsWithSongs - از پایگاه داده پرس و جو میکند و تمام اشیاء
PlaylistWithSongsحاصل را برمیگرداند. -
getSongsWithPlaylists - از پایگاه داده پرس و جو میکند و تمام اشیاء
SongWithPlaylistsحاصل را برمیگرداند.
هر تابع به Room نیاز دارد تا دو کوئری اجرا کند. برای اطمینان از اجرای خودکار عملیات، حاشیهنویسی @Transaction را به هر دو تابع اضافه کنید.
@Transaction @Query("SELECT * FROM Playlist") suspend fun getPlaylistsWithSongs(): List<PlaylistWithSongs> @Transaction @Query("SELECT * FROM Song") suspend fun getSongsWithPlaylists(): List<SongWithPlaylists>
کلیدهای ترکیبی
اگر رابطه را با استفاده از کلیدهای مرکب تعریف میکنید، چندین ستون را در parentColumns و entityColumns از حاشیهنویسی @Relation مشخص کنید.
اگر نیاز دارید ستونهایی را در Junction مشخص کنید، parentColumns و entityColumns نیز در حاشیهنویسی Junction استفاده کنید.
در مثال زیر، Playlist یک کلید اصلی مرکب متشکل از playlistId و creatorId دارد. جدول ارجاع متقابل PlaylistSongCrossRef نیز شامل این ستونها برای ارجاع به لیست پخش است.
@Entity(primaryKeys = ["playlistId", "creatorId"]) data class Playlist( val playlistId: Long, val creatorId: Long, val playlistName: String ) @Entity data class Song( @PrimaryKey val songId: Long, val songName: String, val artist: String ) @Entity(primaryKeys = ["playlistId", "creatorId", "songId"]) data class PlaylistSongCrossRef( val playlistId: Long, val creatorId: Long, val songId: Long ) data class PlaylistWithSongs( @Embedded val playlist: Playlist, @Relation( parentColumns = ["playlistId", "creatorId"], entityColumns = ["songId"], associateBy = Junction(PlaylistSongCrossRef::class) ) val songs: List<Song> )