【Kotlin/Room】リレーションしたエンティティを一括で取得する方法!@Embeddedと@Relation
この記事からわかること
- Android Studio/KotlinでRoomデータベースの使い方
- テーブル同士を連携する方法
- リレーションしたエンティティを一括で取得するには?
- @Embeddedと@Relationを使用したリレーション
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
Roomで2つのテーブルにリレーションを設定する方法
前回の記事でRoomで2つのテーブル間のリレーションを実装しましたが、これは親が削除された時に該当する子も削除されるということでした。なので厳密にはリレーション関係が結ばれているのはデータの削除時のみであり、取得する際には別々で取得したり、フィルタリングする必要がありました。
今回はデータベースに蓄積してあるデータをテーブルの関係性を維持して取得する方法をまとめていきます。
@Embeddedと@Relationで中間クラスを作成する
公式より推奨されているのが@Embeddedと@Relationアノテーションを使用して親と子の両方を保持する中間クラスを作成する方法です。
@Embedded
@Embedded
アノテーションはエンティティのフィールドに独自の別のエンティティを指定したい場合に利用できるアノテーションです。
@Relation
@Relation
アノテーションは親と子の関連づけを定義するためのアノテーションです。
一括で取得するメソッドを実装してみる
前回と同じエンティティを使用していきます。まずは親となるCompany
クラスと子となるPerson
クラスの定義です。ここは前回から変化していません。
親:Companyエンティティクラス
@Entity(tableName = "company_table")
data class Company (
@PrimaryKey(autoGenerate = true) val id: Int,
val name: String,
)
子:Personエンティティクラス
@Entity(tableName = "person_table",
foreignKeys = arrayOf(
ForeignKey(
entity = Company::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("companyId"),
onDelete = ForeignKey.CASCADE
)
)
)
data class Person (
@PrimaryKey(autoGenerate = true) val id: Int,
val name: String,
val companyId: Int
)
この2つのエンティティクラスの中間エンティティクラス(CompanyWithPersons)を新規で作成します。このエンティティはフィールドに親1つと複数の子を持つことで一対多の関係性を保持しています。
子:CompanyWithPersons中間エンティティクラス
data class CompanyWithPersons (
@Embedded val company: Company,
@Relation(
parentColumn = "id",
entityColumn = "companyId"
)
val persons: List<Person>
)
親となるCompany
には@Embedded
アノテーションを付与します。これでこのフィールドはCompany
エンティティ扱いになります。
子となるPerson
は複数保持するのでList形式のフィールドを定義し、@Relation
アノテーションを付与します。引数parentColumn
やentityColumn
にはForeignKey
で指定したものを同じ値を渡します。
Daoに@Transactionを付与したメソッドを定義
続いてDaoの中に@Transactionアノテーションを付与した専用の取得メソッドを用意します。このメソッドでは親エンティティと子エンティティをそれぞれ取得するため2回クエリが実行される必要がありますが、@Transaction
(トランザクション)アノテーションを付与することでまとめて処理させることができるようです。
@Transaction
@Query("SELECT * FROM company_table")
fun getCompanyWithPersons(): List<CompanyWithPersons>
あとはList形式のCompanyWithPersons
型で取得できるので好きなように扱うだけです。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。