กําหนดและค้นหาความสัมพันธ์แบบซ้อน

บางครั้งคุณอาจต้องค้นหาชุดตารางตั้งแต่ 3 ตารางขึ้นไปที่มีความเกี่ยวข้องกันทั้งหมด ในกรณีนี้ คุณต้องกําหนดความสัมพันธ์ที่ฝังระหว่างตาราง

สมมติว่าในตัวอย่างนี้ของแอปสตรีมมิงเพลง คุณต้องการค้นหาผู้ใช้ทั้งหมด เพลย์ลิสต์ทั้งหมดของผู้ใช้แต่ละราย และเพลงทั้งหมดในเพลย์ลิสต์แต่ละรายการของผู้ใช้แต่ละราย ผู้ใช้มีความสัมพันธ์แบบ 1: หลายกับเพลย์ลิสต์ และเพลย์ลิสต์มีความสัมพันธ์แบบหลายต่อหลายกับเพลง ตัวอย่างโค้ดต่อไปนี้แสดงคลาสที่แสดงถึงเอนทิตีเหล่านี้ รวมถึงตารางการอ้างอิงข้ามสำหรับความสัมพันธ์แบบหลายต่อหลายระหว่างเพลย์ลิสต์กับเพลง

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 ที่ใช้โมเดลความสัมพันธ์แบบ 1: หลายระหว่างคลาสเอนทิตี 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

UserWithPlaylistsAndSongs แสดงความสัมพันธ์ระหว่าง User กับ PlaylistWithSongs ซึ่งจะแสดงความสัมพันธ์ระหว่าง 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();