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