Relationships 1&2: Mastery Test 3 Pg 271 Ten Steps to Improving College Reading Skills

Considering SQLite is a relational database, you tin can define relationships between entities. Even though most object-relational mapping libraries allow entity objects to reference each other, Room explicitly forbids this. To learn about the technical reasoning behind this determination, see Empathise why Room doesn't allow object references.

2 possible approaches

In Room, there are 2 means to ascertain and query a human relationship between entities: you can model the relationship using either an intermediate data class with embedded objects, or a relational query method with a multimap return type.

Intermediate data form

In the intermediate data grade approach, y'all define a information course that models the relationship between your Room entities. This data class holds the pairings between instances of 1 entity and instances of some other entity equally embedded objects. Your query methods tin can then return instances of this data grade for use in your app.

For example, you can define a UserBook data course to represent library users with specific books checked out, and define a query method to retrieve a listing of UserBook instances from the database:

Kotlin

@Dao interface UserBookDao {     @Query(         "SELECT user.name Every bit userName, book.proper name AS bookName " +         "FROM user, book " +         "WHERE user.id = volume.user_id"     )     fun loadUserAndBookNames(): LiveData<Listing<UserBook>> }  data class UserBook(val userName: String?, val bookName: String?)            

Coffee

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

Multimap render types

In the multimap render blazon approach, you don't need to ascertain whatever additional information classes. Instead, you lot define a multimap return type for your method based on the map structure that you lot desire and define the relationship between your entities directly in your SQL query.

For example, the post-obit query method returns a mapping of User and Book instances to stand for library users with specific books checked out:

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();            

Choose an approach

Room supports both of the approaches described above, and you should use whichever approach works all-time for your app. This department discusses some of the reasons why you might prefer i or the other.

The intermediate data class approach allows you to avoid writing complex SQL queries, but it can as well upshot in increased code complexity due to the additional information classes that information technology requires. In brusk, the multimap return type approach requires your SQL queries to do more work; and the intermediate data grade arroyo requires your code to practise more work.

If you don't have a specific reason to use intermediate information classes, we recommend that you use the multimap render blazon approach. To acquire more than almost this approach, see Return a multimap.

The rest of this guide demonstrates how to define relationships using the intermediate data class arroyo.

Create embedded objects

Sometimes, you'd like to express an entity or data object as a cohesive whole in your database logic, even if the object contains several fields. In these situations, you lot can use the @Embedded annotation to represent an object that you'd like to decompose into its subfields inside a table. You can then query the embedded fields just as you would for other individual columns.

For instance, your User class can include a field of type Accost, which represents a composition of fields named street, city, state, and postCode. To store the composed columns separately in the table, include an Address field in the User class that is annotated with @Embedded, as shown in the following code snippet:

Kotlin

data class Address(     val street: Cord?,     val state: String?,     val urban center: String?,     @ColumnInfo(name = "post_code") val postCode: Int )  @Entity information grade User(     @PrimaryKey val id: Int,     val firstName: String?,              @Embedded val address: Address?              )            

Coffee

public class Accost {     public String street;     public Cord state;     public String city;      @ColumnInfo(proper name = "post_code") public int postCode; }  @Entity public class User {     @PrimaryKey public int id;      public Cord firstName;              @Embedded public Address accost;              }            

The table representing a User object then contains columns with the following names: id, firstName, street, country, city, and post_code.

If an entity has multiple embedded fields of the aforementioned blazon, you can keep each cavalcade unique by setting the prefix holding. Room then adds the provided value to the beginning of each column proper noun in the embedded object.

Define one-to-one relationships

A one-to-one relationship between two entities is a relationship where each instance of the parent entity corresponds to exactly 1 instance of the kid entity, and vice-versa.

For example, consider a music streaming app where the user has a library of songs that they own. Each user has simply one library, and each library corresponds to exactly i user. Therefore, in that location should be a one-to-ane relationship between the User entity and the Library entity.

First, create a form for each of your two entities. One of the entities must include a variable that is a reference to the primary key of the other entity.

Kotlin

@Entity data class User(     @PrimaryKey val userId: Long,     val proper name: String,     val historic period: 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 historic period; }  @Entity public class Library {     @PrimaryKey public long libraryId;     public long userOwnerId; }            

In order to query the list of users and corresponding libraries, yous must first model the i-to-one relationship between the two entities. To do this, create a new data grade where each instance holds an instance of the parent entity and the corresponding instance of the kid entity. Add the @Relation annotation to the instance of the child entity, with parentColumn set to the name of the master primal column of the parent entity and entityColumn set to the proper noun of the cavalcade of the child entity that references the parent entity's chief key.

Kotlin

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

Finally, add a method to the DAO class that returns all instances of the data class that pairs the parent entity and the kid entity. This method requires Room to run two queries, so add the @Transaction annotation to this method to ensure that the whole operation is performed atomically.

Kotlin

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

Java

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

Ascertain one-to-many relationships

A 1-to-many relationship betwixt two entities is a relationship where each instance of the parent entity corresponds to naught or more instances of the child entity, but each example of the child entity can but stand for to exactly one instance of the parent entity.

In the music streaming app example, suppose the user has the power to organize their songs into playlists. Each user can create as many playlists as they want, but each playlist is created by exactly ane user. Therefore, there should be a i-to-many relationship betwixt the User entity and the Playlist entity.

First, create a class for each of your 2 entities. As in the previous example, the child entity must include a variable that is a reference to the primary fundamental of the parent entity.

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 course User {     @PrimaryKey public long userId;     public String proper noun;     public int age; }  @Entity public class Playlist {     @PrimaryKey public long playlistId;     public long userCreatorId;     public Cord playlistName; }            

In society to query the list of users and corresponding playlists, you lot must get-go model the one-to-many relationship between the two entities. To do this, create a new data form where each instance holds an example of the parent entity and a list of all corresponding child entity instances. Add the @Relation annotation to the case of the child entity, with parentColumn set to the name of the primary key column of the parent entity and entityColumn set to the name of the column of the child entity that references the parent entity's primary fundamental.

Kotlin

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

Coffee

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

Finally, add a method to the DAO class that returns all instances of the data grade that pairs the parent entity and the child entity. This method requires Room to run two queries, so add together the @Transaction annotation to this method to ensure that the whole operation is performed atomically.

Kotlin

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

Java

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

Define many-to-many relationships

A many-to-many human relationship between two entities is a relationship where each instance of the parent entity corresponds to zero or more instances of the kid entity, and vice-versa.

In the music streaming app instance, consider once again the user-defined playlists. Each playlist can include many songs, and each song tin be a function of many different playlists. Therefore, there should be a many-to-many relationship between the Playlist entity and the Song entity.

First, create a grade for each of your 2 entities. Many-to-many relationships are distinct from other relationship types because at that place is generally no reference to the parent entity in the kid entity. Instead, create a 3rd class to correspond an associative entity (or cross-reference table) between the two entities. The cross-reference table must take columns for the master fundamental from each entity in the many-to-many relationship represented in the table. In this example, each row in the cross-reference table corresponds to a pairing of a Playlist instance and a Song case where the referenced song is included in the referenced playlist.

Kotlin

@Entity data class Playlist(     @PrimaryKey val playlistId: Long,     val playlistName: Cord )  @Entity data class Song(     @PrimaryKey val songId: Long,     val songName: String,     val creative person: Cord )  @Entity(primaryKeys = ["playlistId", "songId"]) information class PlaylistSongCrossRef(     val playlistId: Long,     val songId: Long )            

Java

@Entity public class Playlist {     @PrimaryKey public long playlistId;     public String playlistName; }  @Entity public form Vocal {     @PrimaryKey public long songId;     public String songName;     public String artist; }  @Entity(primaryKeys = {"playlistId", "songId"}) public class PlaylistSongCrossRef {     public long playlistId;     public long songId; }            

The next step depends on how you want to query these related entities.

  • If you want to query playlists and a list of the corresponding songs for each playlist, create a new data class that contains a single Playlist object and a list of all of the Song objects that the playlist includes.
  • If you want to query songs and a listing of the respective playlists for each, create a new information class that contains a unmarried Song object and a listing of all of the Playlist objects in which the vocal is included.

In either case, model the human relationship between the entities by using the associateBy property in the @Relation annotation in each of these classes to identify the cross-reference entity providing the relationship between the Playlist entity and the Vocal entity.

Kotlin

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

Java

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

Finally, add together a method to the DAO class to expose the query functionality your app needs.

  • getPlaylistsWithSongs: This method queries the database and returns all of the resulting PlaylistWithSongs objects.
  • getSongsWithPlaylists: This method queries the database and returns all of the resulting SongWithPlaylists objects.

These methods each crave Room to run 2 queries, and then add the @Transaction annotation to both methods to ensure that the whole operation is performed atomically.

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 Listing<PlaylistWithSongs> getPlaylistsWithSongs();  @Transaction @Query("SELECT * FROM Song") public List<SongWithPlaylists> getSongsWithPlaylists();            

Define nested relationships

Sometimes, you might need to query a set of three or more tables that are all related to each other. In that instance, you would ascertain nested relationships between the tables.

Suppose that in the music streaming app example, you desire to query all of the users, all of the playlists for each user, and all of the songs in each playlist for each user. Users have a one-to-many relationship with playlists, and playlists have a many-to-many human relationship with songs. The post-obit lawmaking example shows the classes that represent these entities, also as the cross-reference table for the many-to-many relationship between playlists and songs:

Kotlin

@Entity data class User(     @PrimaryKey val userId: Long,     val name: Cord,     val age: Int )  @Entity information grade Playlist(     @PrimaryKey val playlistId: Long,     val userCreatorId: Long,     val playlistName: String )  @Entity data class Song(     @PrimaryKey val songId: Long,     val songName: String,     val artist: Cord )  @Entity(primaryKeys = ["playlistId", "songId"]) data form PlaylistSongCrossRef(     val playlistId: Long,     val songId: Long )            

Java

@Entity public course User {     @PrimaryKey public long userId;     public String name;     public int age; }  @Entity public grade Playlist {     @PrimaryKey public long playlistId;     public long userCreatorId;     public String playlistName; } @Entity public class Vocal {     @PrimaryKey public long songId;     public Cord songName;     public Cord artist; }  @Entity(primaryKeys = {"playlistId", "songId"}) public course PlaylistSongCrossRef {     public long playlistId;     public long songId; }            

Showtime, model the relationship betwixt two of the tables in your fix every bit you normally would, with a data class and the @Relation annotation. The following example shows a PlaylistWithSongs class that models a many-to-many human relationship between the Playlist entity class and the Vocal entity class:

Kotlin

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

Java

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

Afterward y'all define a information class that represents this relationship, create another data class that models the relationship between another tabular array from your set and the first human relationship class, "nesting" the existing relationship within the new one. The post-obit instance shows a UserWithPlaylistsAndSongs form that models a 1-to-many human relationship between the User entity form and the PlaylistWithSongs relationship class:

Kotlin

data class UserWithPlaylistsAndSongs(     @Embedded val user: User     @Relation(         entity = Playlist::form,         parentColumn = "userId",         entityColumn = "userCreatorId"     )     val playlists: Listing<PlaylistWithSongs> )            

Coffee

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

The UserWithPlaylistsAndSongs class indirectly models the relationships between all iii of the entity classes: User, Playlist, and Song. This is illustrated in effigy i.

UserWithPlaylistsAndSongs models the relationship between User and    PlaylistWithSongs, which in turn models the relationship between Playlist    and Song.

Effigy 1. Diagram of relationship classes in the music streaming app example.

If at that place are any more tables in your set, create a form to model the relationship between each remaining table and the relationship class that models the relationships betwixt all previous tables. This creates a chain of nested relationships between all of the tables that you want to query.

Finally, add a method to the DAO class to expose the query functionality that your app needs. This method requires Room to run multiple queries, and then add the @Transaction notation to ensure that the whole operation is performed atomically:

Kotlin

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

Java

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

Additional Resources

To learn more than almost defining relationships between entities in Room, see the post-obit additional resources.

Samples

  • Android Sunflower
  • Tivi

Videos

  • What's New in Room (Android Dev Tiptop '19)

Blogs

  • Database relations with Room

grandefeeirid.blogspot.com

Source: https://developer.android.com/training/data-storage/room/relationships

0 Response to "Relationships 1&2: Mastery Test 3 Pg 271 Ten Steps to Improving College Reading Skills"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel