گاهی اوقات، ممکن است نیاز داشته باشید مجموعهای از سه یا چند جدول را که همگی به یکدیگر مرتبط هستند، جستجو کنید. در این صورت، باید روابط تو در تو بین جداول تعریف کنید.
فرض کنید در مثال برنامه پخش موسیقی، میخواهید از همه کاربران، همه لیستهای پخش برای هر کاربر و همه آهنگهای موجود در هر لیست پخش برای هر کاربر، کوئری بگیرید. کاربران با لیستهای پخش رابطه یک به چند دارند و لیستهای پخش با آهنگها رابطه چند به چند دارند. مثال کد زیر کلاسهایی را که نمایانگر این موجودیتها هستند و همچنین جدول ارجاع متقابل برای رابطه چند به چند بین لیستهای پخش و آهنگها را نشان میدهد:
کاتلین
@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"])
data class PlaylistSongCrossRef(
val playlistId: Long,
val songId: Long
)
جاوا
@Entity
public class User {
@PrimaryKey public long userId;
public String name;
public int age;
}
@Entity
public class Playlist {
@PrimaryKey public long playlistId;
public long userCreatorId;
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;
}
ابتدا، رابطه بین دو جدول در مجموعه خود را طبق معمول، با استفاده از یک کلاس داده و حاشیهنویسی @Relation مدلسازی کنید. مثال زیر یک کلاس PlaylistWithSongs را نشان میدهد که یک رابطه چند به چند بین کلاس موجودیت Playlist و کلاس موجودیت Song مدلسازی میکند:
کاتلین
data class PlaylistWithSongs(
@Embedded val playlist: Playlist,
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef::class)
)
val songs: List<Song>
)
جاوا
public class PlaylistWithSongs {
@Embedded public Playlist playlist;
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef.class)
)
public List<Song> songs;
}
پس از تعریف یک کلاس داده که این رابطه را نشان میدهد، یک کلاس داده دیگر ایجاد کنید که رابطه بین جدول دیگری از مجموعه شما و کلاس رابطه اول را مدلسازی کند و رابطه موجود را درون رابطه جدید "تو در تو" کند. مثال زیر یک کلاس UserWithPlaylistsAndSongs را نشان میدهد که یک رابطه یک به چند بین کلاس موجودیت User و کلاس رابطه PlaylistWithSongs مدلسازی میکند:
کاتلین
data class UserWithPlaylistsAndSongs(
@Embedded val user: User
@Relation(
entity = Playlist::class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
val playlists: List<PlaylistWithSongs>
)
جاوا
public class UserWithPlaylistsAndSongs {
@Embedded public User user;
@Relation(
entity = Playlist.class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
public List<PlaylistWithSongs> playlists;
}
کلاس UserWithPlaylistsAndSongs به طور غیرمستقیم روابط بین هر سه کلاس موجودیت: User ، Playlist و Song مدلسازی میکند. این موضوع در شکل 1 نشان داده شده است.

اگر جداول بیشتری در مجموعه شما وجود دارد، یک کلاس برای مدلسازی رابطه بین هر جدول باقیمانده و کلاس رابطهای که روابط بین تمام جداول قبلی را مدلسازی میکند، ایجاد کنید. این کار زنجیرهای از روابط تو در تو بین تمام جداولی که میخواهید پرسوجو کنید، ایجاد میکند.
در نهایت، یک متد به کلاس DAO اضافه کنید تا تابع پرسوجوی مورد نیاز برنامهتان را نمایش دهد. این متد به Room نیاز دارد تا چندین پرسوجو را اجرا کند، بنابراین حاشیهنویسی @Transaction را اضافه کنید تا کل عملیات به صورت خودکار انجام شود:
کاتلین
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>
جاوا
@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylistsAndSongs> getUsersWithPlaylistsAndSongs();