Các mối quan hệ của Entity trong Room

Giới thiệu Chào 500 ae! Hôm nay mình sẽ tiếp tục series tìm hiểu về thư viện Room trong Android. Ở bài trước (Link), chúng ta đã tìm hiểu về Data Access Objects – DAO trong Room. Bây giờ chúng ta sẽ tìm hiểu về các mối quan hệ của Entity trong Room nhé. Vì

Giới thiệu

Chào 500 ae! Hôm nay mình sẽ tiếp tục series tìm hiểu về thư viện Room trong Android.

Ở bài trước (Link), chúng ta đã tìm hiểu về Data Access Objects – DAO trong Room. Bây giờ chúng ta sẽ tìm hiểu về các mối quan hệ của Entity trong Room nhé.

Vì SQLite là một cơ sở dữ liệu quan hệ, các thực thể có thể có mối quan hệ giữa chúng. Trong Room, các thực thể không thể tham chiếu trực tiếp đến các thực thể khác vì nó có thể gây tải dữ liệu không cần thiết mọi lúc.

Tuy nhiên, đôi khi, bạn muốn tham chiếu đến các thực thể khác từ thực thể của mình. Bạn có thể đạt được điều này bằng nhiều cách.

Embedded Objects

Bạn có thể sử dụng chú thích @Embedded để đại diện cho một đối tượng mà bạn muốn phân tách thành các trường con của nó trong một bảng (entity). Sau đó, bạn có thể truy vấn các trường được nhúng giống như cách bạn làm đối với các cột riêng lẻ khác.

Các trường được nhúng cũng có thể bao gồm các trường được nhúng khác.

dataclassAddress(val street: String?,val state: String?,val city: String?,val postCode: Int
)@EntitydataclassUser(@PrimaryKeyval id: Int,val firstName: String?,@Embeddedval address: Address?)

Sau đó, bảng đại diện cho một đối tượng User chứa các cột có tên sau: id, firstName, street, state, city, và postCode.

Nếu một thực thể có nhiều trường nhúng cùng loại, bạn có thể giữ cho mỗi cột là duy nhất bằng cách đặt thuộc tính prefix. Sau đó, Room sẽ thêm giá trị được cung cấp vào đầu mỗi tên cột trong đối tượng được nhúng.

Trong ví dụ trên, các trường của một đối tượng được phân tách thành một thực thể. Trong trường hợp bạn muốn thể hiện mối quan hệ giữa nhiều thực thể, bạn không thể sử dụng @Embedded.

Bạn có thể sử dụng tham số chú thích @Relation hoặc foreignkeys của chú thích @Entity để xác định mối quan hệ giữa hai thực thể. Cả hai đều khác biệt với nhau theo cách mà chú thích @Relation chỉ có thể được áp dụng trên một lớp không phải thực thể trong khi ForeignKey được sử dụng trên một lớp thực thể. Ngoài ra, ForeignKey ảnh hưởng đến lược đồ của một thực thể yêu cầu (các) cột con tồn tại trong (các) cột mẹ. @Relation được sử dụng để nối các bảng mà không ảnh hưởng đến lược đồ của các bảng.

Bạn có thể xác định mối quan hệ giữa các thực thể theo 3 cách:

  • Quan hệ 1-1
  • Quan hệ 1- nhiều
  • Quan hệ nhiều – nhiều

Quan hệ 1-1

Mối quan hệ 1-1 giữa hai thực thể là mối quan hệ trong đó mỗi cá thể của thực thể mẹ tương ứng với chính xác một phiên bản của thực thể con và ngược lại.

Ví dụ: hãy xem xét một ứng dụng phát trực tuyến nhạc mà người dùng có một thư viện các bài hát mà họ sở hữu. Mỗi người dùng chỉ có một thư viện và mỗi thư viện tương ứng với chính xác một người dùng.

@EntitydataclassUser(@PrimaryKeyval userId: Long,val name: String,val age: Int
)@Entity(foreignKeys =@ForeignKey(entity = User.class,
    parentColumns ="userId",
    childColumns ="userOwnerId",
    onDelete = CASCADE))dataclassLibrary(@PrimaryKeyval libraryId: Long,val title: String,val userOwnerId: Long
)dataclassUserAndLibrary(@Embeddedval user: User,@Relation(
      parentColumn ="userId",
      entityColumn ="userOwnerId")val library: Library
)

Trong ví dụ trên, UserLibrary là các thực thể có mối quan hệ một-một. Một trong các thực thể phải bao gồm một biến là tham chiếu đến khóa chính của thực thể kia (userOwnerId trong thực thể Library).

Để truy vấn danh sách người dùng và các thư viện tương ứng, trước tiên chúng ta phải mô hình hóa mối quan hệ 1-1 giữa hai thực thể, được thực hiện bằng cách sử dụng lớp UserAndLibrary. Lớp UserAndLibrary chứa một thể hiện của thực thể mẹ User và thể hiện tương ứng của thực thể con Library. Sau đó, thêm chú thích @Relation vào phiên bản của thực thể con, với parentColumn được đặt thành tên của cột khóa chính của thực thể mẹ và entityColumn được đặt thành tên của cột của thực thể con tham chiếu đến khóa chính của thực thể mẹ.

Bây giờ chúng ta có thể truy vấn cơ sở dữ liệu của mình theo cách sau:

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

Quan hệ 1-Nhiều

Mối quan hệ một-nhiều giữa hai thực thể là mối quan hệ trong đó mỗi cá thể của thực thể mẹ tương ứng với không hoặc nhiều cá thể của thực thể con, nhưng mỗi thể hiện của thực thể con chỉ có thể tương ứng với chính xác một thể hiện của thực thể mẹ.

Trong ví dụ về ứng dụng phát trực tuyến nhạc trước, một User có thể có nhiều playlists. Mỗi người dùng có thể tạo bao nhiêu danh sách phát tùy thích, nhưng mỗi danh sách phát được tạo bởi chính xác một người dùng.

@EntitydataclassUser(@PrimaryKeyval userId: Long,val name: String,val age: Int
)@Entity(foreignKeys =@ForeignKey(entity = User.class,
    parentColumns ="userId",
    childColumns ="userCreatorId",
    onDelete = CASCADE))dataclassPlaylist(@PrimaryKeyval playlistId: Long,val userCreatorId: Long,val playlistName: String
)dataclassUserWithPlaylists(@Embeddedval user: User,@Relation(
      parentColumn ="userId",
      entityColumn ="userCreatorId")val playlists: List<Playlist>)

Như chúng ta có thể thấy, cách tiếp cận rất giống với mối quan hệ 1-1, sự khác biệt duy nhất ở đây là trong mô hình mối quan hệ (UserWithPlaylists). Thay vì chứa một thực thể con, giờ đây nó chứa một danh sách các thực thể con. Truy vấn cơ sở dữ liệu cũng rất tương tự.

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

Quan hệ Nhiều-Nhiều

Mối quan hệ nhiều-nhiều giữa hai thực thể là mối quan hệ trong đó mỗi cá thể của thực thể mẹ tương ứng với không hoặc nhiều cá thể của thực thể con và ngược lại.

Trong ví dụ về ứng dụng phát trực tuyến nhạc, mỗi danh sách phát có thể bao gồm nhiều bài hát và mỗi bài hát có thể là một phần của nhiều danh sách phát khác nhau. Do đó, phải có mối quan hệ nhiều-nhiều giữa thực thể playlist và thực thể Song. Mối quan hệ nhiều-nhiều khác biệt với các kiểu quan hệ khác vì thường không có tham chiếu đến thực thể mẹ trong thực thể con. Thay vào đó, lớp thứ ba được sử dụng để đại diện cho một thực thể liên kết (hoặc bảng tham chiếu chéo) giữa hai thực thể. Bảng tham chiếu chéo phải có các cột cho khóa chính từ mỗi thực thể trong mối quan hệ nhiều-nhiều được thể hiện trong bảng.

@EntitydataclassPlaylist(@PrimaryKeyval id: Long,val playlistName: String
)@EntitydataclassSong(@PrimaryKeyval id: Long,val songName: String,val artist: String
)@Entity(primaryKeys =["playlistId","songId"],
    foreignKeys ={@ForeignKey(entity = Playlist.class,
      parentColumns ="id",
      childColumns ="playlistId"),@ForeignKey(entity = Song.class,
      parentColumns ="id",
      childColumns ="songId")}))dataclassPlaylistSongCrossRef(val playlistId: Long,val songId: Long
)

Bây giờ, bước tiếp theo phụ thuộc vào cách bạn muốn truy vấn các thực thể liên quan này.

  • Nếu bạn muốn truy vấn playlist và danh sách các bài hát tương ứng cho từng playlist, hãy tạo một lớp dữ liệu mới chứa một đối tượng playlist duy nhất và danh sách tất cả các đối tượng Song mà danh sách phát bao gồm.
  • Nếu bạn muốn truy vấn các bài hát và danh sách các danh sách phát tương ứng cho mỗi bài hát, hãy tạo một lớp dữ liệu mới chứa một đối tượng Song và danh sách tất cả các đối tượng playlist có bài hát đó.

Trong cả hai trường hợp, mô hình hóa mối quan hệ giữa các thực thể bằng cách sử dụng thuộc tính AssociateBy trong chú thích @Relation trong mỗi lớp này để xác định thực thể tham chiếu chéo cung cấp mối quan hệ giữa thực thể Playlist và thực thể Song.

dataclassPlaylistWithSongs(@Embeddedval playlist: Playlist,@Relation(
      parentColumn ="playlistId",
      entityColumn ="songId",
      associateBy =@Junction(PlaylistSongCrossRef::class))val songs: List<Song>)dataclassSongWithPlaylists(@Embeddedval song: Song,@Relation(
      parentColumn ="songId",
      entityColumn ="playlistId",
      associateBy =@Junction(PlaylistSongCrossRef::class))val playlists: List<Playlist>)

Truy vấn cơ sở dữ liệu tương tự như các cách tiếp cận trước đây.

@Transaction@Query("SELECT * FROM Playlist")fungetPlaylistsWithSongs(): List<PlaylistWithSongs>@Transaction@Query("SELECT * FROM Song")fungetSongsWithPlaylists(): List<SongWithPlaylists>

Kết luận

Đây là tất cả về Mối quan hệ thực thể trong Room. Hy vọng bạn thích bài này

Nguồn tham khảo: https://blog.mindorks.com/entity-relationship-in-room

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ