2 つのエンティティ間の 1 対多のリレーションとは、親エンティティの各インスタンスが子エンティティの 0 個以上のインスタンスに対応し、子エンティティの各インスタンスは親エンティティの 1 つのインスタンスにだけ対応するリレーションです。
音楽ストリーミング アプリで、ユーザーがプレイリストに曲を整理できる機能があるとします。各ユーザーが作成できるプレイリストの数に制限はありませんが、各プレイリストの作成者は 1 人だけです。したがって、User
エンティティと Playlist
エンティティの間には 1 対多のリレーションがあります。
データベースで 1 対多のリレーションを定義してクエリを実行する手順は次のとおりです。
- 関係を定義する: 両方のエンティティのクラスを作成し、子エンティティが親の主キーを参照するようにします。
- エンティティをクエリする: 新しいデータクラスでリレーションをモデル化し、関連データを取得するメソッドを実装します。
関係を定義する
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();