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