บางครั้งคุณอาจต้องค้นหาชุดตาราง 3 รายการขึ้นไปที่เกี่ยวข้องกับตารางอื่นๆ ทั้งหมด ในกรณีดังกล่าว ให้กำหนด ความสัมพันธ์แบบซ้อนระหว่างตาราง
สมมติว่าในตัวอย่างแอปสตรีมมิงเพลง คุณต้องการค้นหาผู้ใช้ทั้งหมด เพลย์ลิสต์ทั้งหมดของผู้ใช้แต่ละราย และเพลงทั้งหมดในเพลย์ลิสต์แต่ละรายการของผู้ใช้แต่ละราย ผู้ใช้มีความสัมพันธ์แบบหนึ่งต่อหลายกับเพลย์ลิสต์ และ เพลย์ลิสต์มีความสัมพันธ์แบบหลายต่อหลายกับเพลง ตัวอย่างโค้ดต่อไปนี้แสดงคลาสที่แสดงเอนทิตีเหล่านี้ รวมถึงตารางการอ้างอิงโยงสำหรับความสัมพันธ์แบบหลายต่อหลายระหว่างเพลย์ลิสต์กับเพลง
Kotlin
@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
)
Java
@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;
}
ขั้นแรก ให้สร้างโมเดลความสัมพันธ์ระหว่างตาราง 2 รายการในชุดตามที่คุณ
ทำตามปกติ โดยใช้คลาสข้อมูลและคำอธิบายประกอบ @Relation ตัวอย่างต่อไปนี้แสดงคลาส PlaylistWithSongs ที่สร้างโมเดลความสัมพันธ์แบบหลายต่อหลายระหว่างคลาสเอนทิตี Playlist กับคลาสเอนทิตี Song
Kotlin
data class PlaylistWithSongs(
@Embedded val playlist: Playlist,
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef::class)
)
val songs: List<Song>
)
Java
public class PlaylistWithSongs {
@Embedded public Playlist playlist;
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef.class)
)
public List<Song> songs;
}
หลังจากกำหนดคลาสข้อมูลที่แสดงความสัมพันธ์นี้แล้ว ให้สร้างคลาสข้อมูลอีกคลาสหนึ่งที่สร้างโมเดลความสัมพันธ์ระหว่างตารางอื่นจากชุดกับคลาสความสัมพันธ์แรก โดย "ซ้อน" ความสัมพันธ์ที่มีอยู่ภายในความสัมพันธ์ใหม่ ตัวอย่างต่อไปนี้แสดงคลาส UserWithPlaylistsAndSongs ที่สร้างโมเดล
ความสัมพันธ์แบบหนึ่งต่อหลายระหว่างคลาสเอนทิตี User กับ
PlaylistWithSongs คลาสความสัมพันธ์:
Kotlin
data class UserWithPlaylistsAndSongs(
@Embedded val user: User
@Relation(
entity = Playlist::class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
val playlists: List<PlaylistWithSongs>
)
Java
public class UserWithPlaylistsAndSongs {
@Embedded public User user;
@Relation(
entity = Playlist.class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
public List<PlaylistWithSongs> playlists;
}
คลาส UserWithPlaylistsAndSongs สร้างโมเดลความสัมพันธ์
ระหว่างคลาสเอนทิตีทั้ง 3 คลาส ได้แก่ User, Playlist, และ Song โดยอ้อม ซึ่งแสดงไว้ในรูปที่ 1
หากมีตารางอื่นๆ ในชุด ให้สร้างคลาสเพื่อสร้างโมเดลความสัมพันธ์ระหว่างตารางที่เหลือแต่ละรายการกับคลาสความสัมพันธ์ที่สร้างโมเดลความสัมพันธ์ระหว่างตารางก่อนหน้าทั้งหมด ซึ่งจะสร้างความสัมพันธ์แบบซ้อนเป็นห่วงโซ่ระหว่างตารางทั้งหมดที่คุณต้องการค้นหา
สุดท้าย ให้เพิ่มเมธอดลงในคลาส DAO เพื่อแสดงฟังก์ชันการค้นหาที่แอปของคุณต้องการ เมธอดนี้กำหนดให้ Room เรียกใช้การค้นหาหลายรายการ ดังนั้นให้เพิ่มคำอธิบายประกอบ
@Transaction เพื่อให้การดำเนินการทั้งหมดดำเนินการอย่างเป็นหน่วย
Kotlin
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>
Java
@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylistsAndSongs> getUsersWithPlaylistsAndSongs();