〈kotlin〉Room

Android studioでkotlinを使ってAndroidアプリ作成の勉強中。

データベースSQLiteを簡単に扱うことができるRoomの実装をまとめる。

Roomの構成

Roomは以下3つの主要コンポーネントで構成されている。

データエンティティ データベースのテーブル
データアクセスオブジェクト(DAO) データベースを操作するメソッド
データベースクラス データベースを保持する

この3つを順に実装していく。

build.gradle

//Room
implementation "androidx.room:room-runtime:2.4.1"
//アノテーション
kapt "androidx.room:room-compiler:2.4.1"

データエンティティ

@Entity アノテーションを付けたクラスとして定義する。
ここで定義したものがデータベースのテーブル内のカラムになる。

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    val lastName: String?
)

エンティティにはデータベーステーブルの各行を一意に識別するために主キーを含める必要がある。
主キーは@PrimaryKeyのアノテーションをつけて定義する。
autoGenerateをtrueにすることでキーを自動生成することができる。

@PrimaryKey(autoGenerate = true) val id: Int

カラム名はデフォルトでフィールド名が使われるが、
@ColumnInfoアノテーションに記載することで自分で設定できる。
SQLiteカラム名は大文字小文字の区別はされない。)

@ColumnInfo(name = "first_name") val firstName: String?

テーブル名はデフォルトでクラス名が使われるが、
@Entity アノテーションに記載することで自分で設定できる。

@Entity(tableName = "users")

データアクセスオブジェクト(DAO)

DAOはインターフェイスとして定義する。
コンパイル時に、Room が定義した DAO の実装を自動的に生成してくれる。
DAO内にはデータベースを操作する(挿入、更新、削除、クエリ)メソッドを定義する。

@Dao
interface UserDao {
    //以下3つはコンビニエンスメソッド
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)

    @Update
    fun updateUsers(vararg users: User)

    //以下はクエリメソッド
    @Query("SELECT * FROM user")
    fun getAll(): List<User>
}
コンビニエンスメソッド

シンプルな挿入、更新、削除はアノテーションをつけるだけで実装できる。
@Insertに指定したonConflictは、
データ挿入や更新時に重複が発生した場合の挙動を指定する。
デフォルトではABORT(トランザクションを中止)になっている。

クエリメソッド

複雑な処理やデータをクエリする場合、
@Queryアノテーションでクエリを記述して定義する。

データベース

@Databaseアノテーションをつけ、RoomDatabase を拡張する抽象クラスとして定義する。
@Databaseアノテーションにはデータベースに関連する全てのエンティティの配列と、
データベースのバージョンを渡す。
クラス内にはデータベースに関連するDAOを、
引数なしでDAO クラスのインスタンスを返す抽象メソッドとして定義する。

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

使用方法

データベースのインスタンスは以下のように作成する。

val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()

データベースの作成後、データベースの抽象メソッドでDAOのインスタンスを取得し、
これを使用することでデータベース操作ができる。

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

注意点

  • クエリが UI をブロックしないように、Room はメインスレッドでのデータベース アクセスを許可していない。
  • データベースのインスタンスは高コストで通常アプリに1つで良いためシングルトンにする。

このあたりは次のブログで。

続き↓
mtnmr.hatenablog.com
mtnmr.hatenablog.com

参考
Room を使用してローカル データベースにデータを保存する  |  Android デベロッパー  |  Android Developers
Room エンティティを使用してデータを定義する  |  Android デベロッパー  |  Android Developers
Room DAO を使用してデータにアクセスする  |  Android デベロッパー  |  Android Developers