【Kotlin/Room】リレーションしたエンティティを一括で取得する方法!@Embeddedと@Relation

この記事からわかること

  • Android Studio/KotlinRoomデータベース使い方
  • テーブル同士連携する方法
  • リレーションしたエンティティ一括取得するには?
  • @Embedded@Relation使用したリレーション

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

Roomで2つのテーブルにリレーションを設定する方法

前回の記事でRoomで2つのテーブル間のリレーションを実装しましたが、これは親が削除された時に該当する子も削除されるということでした。なので厳密にはリレーション関係が結ばれているのはデータの削除時のみであり、取得する際には別々で取得したり、フィルタリングする必要がありました。

今回はデータベースに蓄積してあるデータをテーブルの関係性を維持して取得する方法をまとめていきます。

@Embeddedと@Relationで中間クラスを作成する

公式リファレンス:1 対多のリレーションを定義する

公式より推奨されているのが@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アノテーションを付与します。引数parentColumnentityColumnにはForeignKeyで指定したものを同じ値を渡します。

Daoに@Transactionを付与したメソッドを定義

続いてDaoの中に@Transactionアノテーションを付与した専用の取得メソッドを用意します。このメソッドでは親エンティティと子エンティティをそれぞれ取得するため2回クエリが実行される必要がありますが、@Transaction(トランザクション)アノテーションを付与することでまとめて処理させることができるようです。

@Transaction
@Query("SELECT * FROM company_table")
fun getCompanyWithPersons(): List<CompanyWithPersons>

あとはList形式のCompanyWithPersons型で取得できるので好きなように扱うだけです。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index