Mối quan hệ một với nhiều giữa hai thực thể là mối quan hệ trong đó mỗi bản sao của thực thể mẹ tương ứng với không hoặc nhiều bản sao của thực thể con, nhưng mỗi bản sao của thực thể con chỉ có thể tương ứng với đúng một bản sao của thực thể mẹ.
Trong ví dụ về ứng dụng phát nhạc trực tuyến, giả sử người dùng có thể sắp xếp các bài hát của họ vào danh sách phát. Mỗi người dùng có thể tạo số lượng danh sách phát tuỳ thích nhưng mỗi danh sách phát chỉ do duy nhất 1 người dùng tạo ra. Do đó, có mối quan hệ một với nhiều giữa thực thể User và thực thể Playlist.
Hãy làm theo các bước sau để xác định và truy vấn mối quan hệ một với nhiều trong cơ sở dữ liệu của bạn:
- Xác định mối quan hệ: Tạo các lớp cho cả hai thực thể, trong đó thực thể con tham chiếu đến khoá chính của thực thể mẹ.
- Truy vấn các thực thể: Mô hình hoá mối quan hệ trong một lớp dữ liệu mới và triển khai một hàm để truy xuất dữ liệu có liên quan.
Xác định mối quan hệ
Để xác định mối quan hệ một với nhiều, trước tiên, hãy tạo một lớp cho mỗi thực thể. Như trong mối quan hệ một với một, thực thể con phải bao gồm một biến tham chiếu đến khoá chính của thực thể mẹ.
@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 )
Truy vấn các thực thể
Để truy vấn danh sách người dùng và danh sách phát tương ứng, trước tiên, bạn phải mô hình hoá mối quan hệ một với nhiều giữa 2 thực thể.
Để mô hình hoá mối quan hệ, hãy tạo một lớp dữ liệu mới. Mỗi thực thể của lớp này sẽ chứa một thực thể của thực thể mẹ và một danh sách tất cả các thực thể con tương ứng.
Thêm chú thích @Relation vào thuộc tính đại diện cho danh sách thực thể con. Đặt parentColumns thành tên của cột khoá chính của thực thể mẹ và đặt entityColumns thành tên của cột của thực thể con tham chiếu đến khoá chính của thực thể mẹ.
data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["userId"], entityColumns = ["userCreatorId"] ) val playlists: List<Playlist> )
Cuối cùng, hãy thêm một hàm vào lớp đối tượng truy cập dữ liệu (DAO) để trả về tất cả các thực thể của lớp dữ liệu ghép nối thực thể mẹ và thực thể con.
Thêm chú giải @Transaction để Room thực hiện toàn bộ thao tác một cách tỉ mỉ. Chú giải này là cần thiết vì hàm yêu cầu Room chạy 2 truy vấn.
@Transaction @Query("SELECT * FROM User") suspend fun getUsersWithPlaylists(): List<UserWithPlaylists>
Khoá kết hợp
Nếu bạn xác định mối quan hệ bằng khoá kết hợp, hãy chỉ định nhiều cột trong parentColumns và entityColumns. Thứ tự của các cột trong parentColumns phải khớp với thứ tự của các cột trong entityColumns.
@Entity(primaryKeys = ["firstName", "lastName"]) data class User( val firstName: String, val lastName: String, val age: Int ) @Entity data class Playlist( @PrimaryKey val playlistId: Long, val userFirstName: String, val userLastName: String, val playlistName: String ) data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["firstName", "lastName"], entityColumns = ["userFirstName", "userLastName"] ) val playlists: List<Playlist> )