กำหนดความสัมพันธ์ระหว่างออบเจ็กต์

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

2 วิธีที่เป็นไปได้

กําหนดและค้นหาความสัมพันธ์ระหว่างเอนทิตีในห้องแชทได้ 2 วิธี ดังนี้ ที่ใช้คลาสข้อมูลระดับกลางกับ ออบเจ็กต์ที่ฝังหรือวิธีการค้นหาเชิงสัมพันธ์ที่มีการส่งคืนมัลติแมป ประเภท

คลาสข้อมูลระดับกลาง

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

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

Kotlin

@Dao
interface UserBookDao {
    @Query(
        "SELECT user.name AS userName, book.name AS bookName " +
        "FROM user, book " +
        "WHERE user.id = book.user_id"
    )
    fun loadUserAndBookNames(): LiveData<List<UserBook>>
}

data class UserBook(val userName: String?, val bookName: String?)

Java

@Dao
public interface UserBookDao {
   @Query("SELECT user.name AS userName, book.name AS bookName " +
          "FROM user, book " +
          "WHERE user.id = book.user_id")
   public LiveData<List<UserBook>> loadUserAndBookNames();
}

public class UserBook {
    public String userName;
    public String bookName;
}

ประเภทการแสดงผลแบบหลายแมป

ในแนวทางประเภทการคืนสินค้าแบบหลายแมป คุณไม่จำเป็นต้องระบุเพิ่มเติม คลาสข้อมูล แต่คุณจะกําหนด multimap ผลลัพธ์ประเภทสำหรับ ของคุณตามโครงสร้างแผนที่ที่คุณต้องการและกำหนดความสัมพันธ์ ระหว่างเอนทิตีได้โดยตรงในคำสั่ง SQL

ตัวอย่างเช่น วิธีการค้นหาต่อไปนี้จะแสดงการแมป User และ Book อินสแตนซ์เพื่อเป็นตัวแทนผู้ใช้ห้องสมุดที่มีหนังสือบางเล่มที่ชำระเงินแล้ว:

Kotlin

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>

Java

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id"
)
public Map<User, List<Book>> loadUserAndBookNames();

เลือกวิธีการ

Room รองรับทั้ง 2 วิธีนี้ คุณจึงใช้ แล้วแต่ว่าวิธีการใดจะเหมาะกับแอปของคุณมากที่สุด ส่วนนี้จะอธิบายเกี่ยวกับ เหตุผลว่าทำไมคุณจึงน่าจะชอบอย่างใดอย่างหนึ่ง

แนวทางคลาสข้อมูลระดับกลางช่วยให้คุณไม่ต้องเขียน SQL ที่ซับซ้อน แต่อาจส่งผลให้โค้ดมีความซับซ้อนยิ่งขึ้นเนื่องจาก คลาสข้อมูลเพิ่มเติมที่จำเป็นต้องใช้ กล่าวโดยสรุปคือ ประเภทผลตอบแทนแบบหลายแผนที่ วิธีนี้ต้องใช้การค้นหา SQL เพื่อให้ทำงานได้มากขึ้น และข้อมูลสื่อกลาง แนวทางของชั้นเรียนต้องใช้โค้ดในการทำงานเพิ่มเติม

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

ส่วนที่เหลือของคู่มือนี้จะสาธิตวิธีการกำหนดความสัมพันธ์โดยใช้ ข้อมูลระดับกลาง

สร้างวัตถุที่ฝัง

บางครั้งคุณต้องการแสดงเอนทิตีหรือออบเจ็กต์ข้อมูลเป็น สอดคล้องกันทั้งหมดในตรรกะฐานข้อมูล แม้ว่าออบเจ็กต์นั้นจะมี ด้วย ในกรณีเหล่านี้ คุณสามารถใช้ @Embedded สำหรับแทนวัตถุที่คุณต้องการแยกย่อย ช่องย่อยภายในตาราง จากนั้น คุณสามารถค้นหาช่องที่ฝังได้เช่นเดียวกับที่คุณค้นหา สำหรับคอลัมน์อื่นๆ แต่ละคอลัมน์

ตัวอย่างเช่น ชั้นเรียน User จะมีช่องประเภท Address ที่ แสดงองค์ประกอบของช่องชื่อ street, city, state และ postCode หากต้องการจัดเก็บคอลัมน์ที่เขียนไว้ต่างหากในตาราง ให้ใส่ Address ในคลาส User ที่มีคำอธิบายประกอบ @Embedded, ในฐานะ ที่แสดงในข้อมูลโค้ดต่อไปนี้

Kotlin

data class Address(
    val street: String?,
    val state: String?,
    val city: String?,
    @ColumnInfo(name = "post_code") val postCode: Int
)

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    @Embedded val address: Address?
)

Java

public class Address {
    public String street;
    public String state;
    public String city;

    @ColumnInfo(name = "post_code") public int postCode;
}

@Entity
public class User {
    @PrimaryKey public int id;

    public String firstName;

    @Embedded public Address address;
}

ตารางที่แสดงออบเจ็กต์ User จะมีคอลัมน์ที่มีข้อมูลต่อไปนี้ ชื่อ: id, firstName, street, state, city และ post_code

หากเอนทิตีมีช่องประเภทเดียวกันที่ฝังอยู่หลายช่อง คุณสามารถเก็บแต่ละช่องไว้ ไม่ซ้ำกัน โดยการตั้งค่า prefix จากนั้นห้องแชทจะเพิ่มค่าที่ระบุลงในส่วนต้นของแต่ละคอลัมน์ ในออบเจ็กต์ที่ฝัง

กำหนดความสัมพันธ์แบบหนึ่งต่อหนึ่ง

ความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่าง 2 เอนทิตีคือความสัมพันธ์ที่แต่ละเอนทิตี อินสแตนซ์ของเอนทิตีหลักสอดคล้องกับอินสแตนซ์ของเอนทิตีย่อยเพียง 1 รายการ และรายการในทางกลับกันก็เป็นจริงเช่นกัน

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

หากต้องการกำหนดความสัมพันธ์แบบหนึ่งต่อหนึ่ง ให้สร้างคลาสสำหรับทั้งสองกลุ่มก่อน เอนทิตี หนึ่งในเอนทิตีต้อง รวมตัวแปรที่เป็นการอ้างอิงไปยังคีย์หลักของเอนทิตีอื่น

Kotlin

@Entity
data class User(
    @PrimaryKey val userId: Long,
    val name: String,
    val age: Int
)

@Entity
data class Library(
    @PrimaryKey val libraryId: Long,
    val userOwnerId: Long
)

Java

@Entity
public class User {
    @PrimaryKey public long userId;
    public String name;
    public int age;
}

@Entity
public class Library {
    @PrimaryKey public long libraryId;
    public long userOwnerId;
}

หากต้องการค้นหารายชื่อผู้ใช้และไลบรารีที่เกี่ยวข้อง ก่อนอื่นคุณต้อง สร้างความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่าง 2 เอนทิตี ในการดำเนินการนี้ ให้สร้าง คลาสข้อมูลใหม่ที่แต่ละอินสแตนซ์มีอินสแตนซ์ของเอนทิตีระดับบนและ อินสแตนซ์ที่เกี่ยวข้องของเอนทิตีย่อย เพิ่ม @Relation คำอธิบายประกอบให้กับอินสแตนซ์ของเอนทิตีย่อย โดยตั้งค่า parentColumn เป็น ชื่อของคอลัมน์คีย์หลักของเอนทิตีระดับบนสุดและ entityColumn ตั้งค่าเป็นชื่อของคอลัมน์ของเอนทิตีย่อยที่อ้างอิงระดับบนสุด คีย์หลักของเอนทิตี

Kotlin

data class UserAndLibrary(
    @Embedded val user: User,
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    val library: Library
)

Java

public class UserAndLibrary {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    public Library library;
}

สุดท้าย เพิ่มเมธอดลงในคลาส DAO ที่ส่งคืนอินสแตนซ์ทั้งหมดของข้อมูล ที่จับคู่เอนทิตีหลักและเอนทิตีย่อย วิธีนี้ต้องใช้ พื้นที่สำหรับเรียกใช้การค้นหา 2 รายการ ดังนั้นให้เพิ่มคำอธิบายประกอบ @Transaction ลงในส่วนนี้ เพื่อให้การดำเนินการทั้งหมดทำงานในแบบอะตอม

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersAndLibraries(): List<UserAndLibrary>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserAndLibrary> getUsersAndLibraries();

กำหนดความสัมพันธ์แบบ 1 ต่อหลายรายการ

ความสัมพันธ์แบบหนึ่งต่อหลายระหว่าง 2 เอนทิตีคือความสัมพันธ์ที่แต่ละเอนทิตี อินสแตนซ์ของเอนทิตีหลักสอดคล้องกับอินสแตนซ์ของหน่วยย่อยเป็นศูนย์หรือมากกว่า แต่เอนทิตีย่อยแต่ละรายการสามารถเชื่อมโยงกับได้เพียงรายการเดียวเท่านั้น ของเอนทิตีหลัก

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

หากต้องการกำหนดความสัมพันธ์แบบหนึ่งต่อหลายรายการ ให้สร้างคลาสสำหรับทั้งสองเอนทิตีก่อน ในความสัมพันธ์แบบหนึ่งต่อหนึ่ง เอนทิตีลูกจะต้องรวมตัวแปรที่ เป็นการอ้างอิงไปยังคีย์หลักของเอนทิตีระดับบน

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
)

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;
}

หากต้องการค้นหารายชื่อผู้ใช้และเพลย์ลิสต์ที่เกี่ยวข้อง ก่อนอื่นคุณต้อง จำลองความสัมพันธ์แบบ 1 ต่อหลายรายการระหว่าง 2 เอนทิตี ในการดำเนินการนี้ ให้สร้าง คลาสข้อมูลใหม่ซึ่งแต่ละอินสแตนซ์จะมีอินสแตนซ์ของเอนทิตีระดับบน รายการของอินสแตนซ์เอนทิตีย่อยที่เกี่ยวข้องทั้งหมด เพิ่ม @Relation คำอธิบายประกอบให้กับอินสแตนซ์ของเอนทิตีย่อย โดยตั้งค่า parentColumn เป็น ชื่อของคอลัมน์คีย์หลักของเอนทิตีระดับบนสุดและ entityColumn ตั้งค่าเป็นชื่อของคอลัมน์ของเอนทิตีย่อยที่อ้างอิงระดับบนสุด คีย์หลักของเอนทิตี

Kotlin

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
          parentColumn = "userId",
          entityColumn = "userCreatorId"
    )
    val playlists: List<Playlist>
)

Java

public class UserWithPlaylists {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userCreatorId"
    )
    public List<Playlist> playlists;
}

สุดท้าย เพิ่มเมธอดลงในคลาส DAO ที่ส่งคืนอินสแตนซ์ทั้งหมดของข้อมูล ที่จับคู่เอนทิตีหลักและเอนทิตีย่อย วิธีนี้ต้องใช้ พื้นที่สำหรับเรียกใช้การค้นหา 2 รายการ ดังนั้นให้เพิ่มคำอธิบายประกอบ @Transaction ลงในส่วนนี้ เพื่อให้การดำเนินการทั้งหมดทำงานในแบบอะตอม

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylists(): List<UserWithPlaylists>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylists> getUsersWithPlaylists();

กำหนดความสัมพันธ์แบบหลายต่อหลาย

ความสัมพันธ์แบบหลายต่อหลายระหว่าง 2 เอนทิตีคือความสัมพันธ์ที่แต่ละเอนทิตี อินสแตนซ์ของเอนทิตีหลักสอดคล้องกับอินสแตนซ์ของหน่วยย่อยเป็นศูนย์หรือมากกว่า และรายการในทางกลับกันก็เป็นจริงเช่นกัน

ในตัวอย่างแอปสตรีมมิงเพลง ให้พิจารณาเพลงในเพลย์ลิสต์ที่ผู้ใช้กำหนด แต่ละเพลย์ลิสต์อาจมีเพลงได้หลายเพลง ซึ่งแต่ละเพลงอาจเป็นส่วนหนึ่ง เพลย์ลิสต์ต่างๆ ดังนั้นจึงมีความสัมพันธ์แบบหลายต่อหลาย ระหว่างเอนทิตี Playlist และเอนทิตี Song

หากต้องการกำหนดความสัมพันธ์แบบหลายต่อหลายรายการ ให้สร้างคลาสสำหรับความสัมพันธ์แบบหลายต่อหลายรายการก่อน เอนทิตี ความสัมพันธ์แบบหลายต่อหลาย จะแตกต่างจากความสัมพันธ์ประเภทอื่นๆ เนื่องจากโดยทั่วไปแล้ว การอ้างอิงไปยังเอนทิตีหลักในเอนทิตีย่อย ให้สร้าง เพื่อแสดงถึงหน่วยงานที่เชื่อมโยงหรือเปรียบเทียบระหว่างบุคคล ตารางระหว่าง 2 เอนทิตี ตารางการอ้างอิงเปรียบเทียบต้องมีคอลัมน์สำหรับ คีย์หลักจากแต่ละเอนทิตีในความสัมพันธ์แบบหลายต่อหลายที่แสดงใน ตาราง ในตัวอย่างนี้ แต่ละแถวในตารางการอ้างอิงเปรียบเทียบจะสอดคล้องกับ การจับคู่อินสแตนซ์ Playlist และอินสแตนซ์ Song ที่มีการอ้างอิง มีเพลงอยู่ในเพลย์ลิสต์ที่อ้างอิง

Kotlin

@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"])
data class PlaylistSongCrossRef(
    val playlistId: Long,
    val songId: Long
)

Java

@Entity
public class Playlist {
    @PrimaryKey public long playlistId;
    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;
}

ขั้นตอนถัดไปจะขึ้นอยู่กับวิธีที่คุณต้องการค้นหาเอนทิตีที่เกี่ยวข้องเหล่านี้

  • หากต้องการค้นหาเพลย์ลิสต์และรายการเพลงที่เกี่ยวข้องกับ เพลย์ลิสต์แต่ละรายการ ให้สร้างคลาสข้อมูลใหม่ที่มีออบเจ็กต์ Playlist เดียว และรายการ Song ทั้งหมดที่เพลย์ลิสต์มี
  • หากต้องการค้นหาเพลงและรายการเพลย์ลิสต์ที่เกี่ยวข้องสำหรับ ให้สร้างคลาสข้อมูลใหม่ที่มีออบเจ็กต์ Song รายการเดียวและชุดรายการ ของออบเจ็กต์ Playlist ทั้งหมดที่มีเพลงดังกล่าว

ไม่ว่าในกรณีใด ให้จำลองความสัมพันธ์ระหว่างเอนทิตีโดยใช้แอตทริบิวต์ associateBy ในคำอธิบายประกอบ @Relation ในแต่ละ คลาสเหล่านี้เพื่อระบุเอนทิตีอ้างอิงเปรียบเทียบที่ให้ความสัมพันธ์ ระหว่างเอนทิตี Playlist และเอนทิตี Song

Kotlin

data class PlaylistWithSongs(
    @Embedded val playlist: Playlist,
    @Relation(
         parentColumn = "playlistId",
         entityColumn = "songId",
         associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val songs: List<Song>
)

data class SongWithPlaylists(
    @Embedded val song: Song,
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val playlists: List<Playlist>
)

Java

public class PlaylistWithSongs {
    @Embedded public Playlist playlist;
    @Relation(
         parentColumn = "playlistId",
         entityColumn = "songId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Song> songs;
}

public class SongWithPlaylists {
    @Embedded public Song song;
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Playlist> playlists;
}

สุดท้าย เพิ่มเมธอดลงในคลาส DAO เพื่อแสดงฟังก์ชันการค้นหา ตามความต้องการของแอป

  • getPlaylistsWithSongs: วิธีนี้จะค้นหาฐานข้อมูลและแสดงผลทั้งหมด ผลลัพธ์ PlaylistWithSongs ออบเจ็กต์
  • getSongsWithPlaylists: วิธีนี้จะค้นหาฐานข้อมูลและแสดงผลทั้งหมด ผลลัพธ์ SongWithPlaylists ออบเจ็กต์

วิธีการเหล่านี้ต้องมีห้องแชทเพื่อเรียกใช้การค้นหา 2 รายการ ดังนั้นให้เพิ่มเมธอด @Transaction ลงในทั้ง 2 วิธีเพื่อให้ทั้ง จะทำงานอย่างปรมาณู

Kotlin

@Transaction
@Query("SELECT * FROM Playlist")
fun getPlaylistsWithSongs(): List<PlaylistWithSongs>

@Transaction
@Query("SELECT * FROM Song")
fun getSongsWithPlaylists(): List<SongWithPlaylists>

Java

@Transaction
@Query("SELECT * FROM Playlist")
public List<PlaylistWithSongs> getPlaylistsWithSongs();

@Transaction
@Query("SELECT * FROM Song")
public List<SongWithPlaylists> getSongsWithPlaylists();

กำหนดความสัมพันธ์ที่ซ้อนกัน

บางครั้งคุณอาจต้องค้นหาชุดตารางตั้งแต่ 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 ที่โมเดล ความสัมพันธ์แบบ 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

UserWithAssignmentsAndSongs สร้างโมเดลความสัมพันธ์ระหว่างผู้ใช้กับ
  เพลย์ลิสต์WithSongs ซึ่งจะเชื่อมโยงความสัมพันธ์ระหว่างเพลย์ลิสต์
  และเพลง

รูปที่ 1 แผนภาพของคลาสความสัมพันธ์ใน ตัวอย่างแอปสตรีมมิงเพลง

หากมีตารางอื่นๆ ในชุด ให้สร้างคลาสเพื่อสร้างโมเดล ความสัมพันธ์ระหว่างแต่ละตารางที่เหลือและคลาสความสัมพันธ์ที่จำลองแบบ ความสัมพันธ์ระหว่างตารางก่อนหน้าทั้งหมด สิ่งนี้จะสร้างห่วงโซ่ของ ในตารางทั้งหมดที่คุณต้องการค้นหา

สุดท้าย เพิ่มเมธอดลงในคลาส DAO เพื่อแสดงฟังก์ชันการค้นหาที่ ที่แอปของคุณต้องใช้ วิธีนี้ต้องใช้ห้องแชทเพื่อเรียกใช้การค้นหาหลายรายการ ดังนั้นให้เพิ่ม คำอธิบายประกอบ @Transaction เพื่อให้การดำเนินการทั้งหมดทำงานได้ในระดับอะตอม:

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylistsAndSongs> getUsersWithPlaylistsAndSongs();

แหล่งข้อมูลเพิ่มเติม

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

ตัวอย่าง

วิดีโอ

บล็อก