1 対多のリレーションを定義してクエリを実行する

2 つのエンティティ間の 1 対多のリレーションとは、親エンティティの各インスタンスが子エンティティの 0 個以上のインスタンスに対応し、子エンティティの各インスタンスは親エンティティの 1 つのインスタンスにだけ対応するリレーションです。

音楽ストリーミング アプリで、ユーザーがプレイリストに曲を整理できる機能があるとします。各ユーザーが作成できるプレイリストの数に制限はありませんが、各プレイリストの作成者は 1 人だけです。したがって、User エンティティと Playlist エンティティの間には 1 対多のリレーションがあります。

データベースで 1 対多のリレーションを定義してクエリを実行する手順は次のとおりです。

  1. 関係を定義する: 両方のエンティティのクラスを作成し、子エンティティが親の主キーを参照するようにします。
  2. エンティティをクエリする: 新しいデータクラスでリレーションをモデル化し、関連データを取得するメソッドを実装します。

関係を定義する

1 対多のリレーションを定義するには、まず 2 つのエンティティのクラスを作成します。1 対 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
)

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

エンティティをクエリする

ユーザーと対応するプレイリストのリストをクエリするには、最初に 2 つのエンティティ間の 1 対多のリレーションをモデル化する必要があります。

このために、親エンティティのインスタンスと、対応する子エンティティのインスタンスのリストを保持する新しいデータクラスを作成します。@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 クラスに追加します。このメソッドでは Room に 2 つのクエリを実行させる必要があるため、@Transaction アノテーションを追加して、操作全体がアトミックに実行されるようにします。

Kotlin

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

Java

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