目的

Googleの公式ライブラリ(だと思う)で、
ローカルにDB設定して永続化や、接続できるライブラリ。
使ってみたメモ

環境

  • Android Studio 4.0.1
  • Kotlin 1.3.50

参照サイト

developers Room を使用してローカル データベースにデータを保存する
developers Room データベースを移行する

はじめに

ここより以降の記載は私の独断と偏見が混ざっています。
認識ミスもあるかもしれないので、ご了承ください。
参照することで発生した責任については負いませんので、ご了承ください。

Roomについて

今回Roomを使うことになった理由として、携わることになった案件でもともと利用していたから。
それで導入した人もただ使えればいいや感で入れているよう

それで、調査して使ってみたが、ものすごく使いづらい。
Room自体リリースされてそこまで時間経ってないので、これからというトコロがあるらしい。
ただ、今後使いやすくなったとして、いまの利用中のアプリへの影響も結構あると思っていて。
現状、私が新規でアプリを作ることになったとしても利用しないと思う。
AndroidでもRealmを使うと思います。
使いにくいと思った理由は以下

  • バックグラウンドスレッドでDB処理しないとエラーになる。(コルーチンオプションを使えば少しは楽!?)
  • DBを取り扱うにあたり、3,4クラス(3,4ファイル)も取り扱う必要がある。(Database、Table, DAO, 必要であればConverter)
  • マイグレーションがめちゃくちゃ面倒くさい(sqlite文をそのまま記載する必要がある。)

違ったらスミマセン。

対応メモ

公式サイトの記載に+アルファで追記しています。
コンバート設定はプライマリキー、updateなどを記載

ライブラリインストール」

以下でライブラリインストール
appのbuild.gradleに記載する。

roomインストール
dependencies {
  def room_version = "2.2.5"

  implementation "androidx.room:room-runtime:$room_version"
  kapt "androidx.room:room-compiler:$room_version"

  // optional - Kotlin Extensions and Coroutines support for Room
  implementation "androidx.room:room-ktx:$room_version"

  // optional - Test helpers
  testImplementation "androidx.room:room-testing:$room_version"
}

DB設定

@Database(entities = arrayOf(User::class), version = 1)
// @TypeConverters(UserConverters::class) sqliteで認識できない型にコンバートする場合
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

テーブル設定

@Entity(primaryKeys = ["uid"])
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

Dao

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    //insert - updateも対応
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

コンバート

object UserConverters {
    @TypeConverter
    fun convertString(value: String?): IntArray? {
        //stringをIntArrayに変換する処理
        return xxxxx
    }

    //上記の逆IntArrayからStringに変換する処理も必要であれば
}

マイグレーション

今後のマイグレーションを見込んで
appのbuild.gradleファイルに以下を設定しておいたほうが良いとのこと。

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["room.schemaLocation":
                             "$projectDir/schemas".toString()]
            }
        }
    }
}

DB読み込み

var database = Room.databaseBuilder(this, AppDatabase::class.java, "AppDatabase").build()

テーブル操作 select

AsyncTask.execute{
    val data = database?.userDao()?.getAll()
    if (data != null) {
        mHandler.post{//メインスレッドで
        if (data.isNotEmpty()) {
            val name = data[0].firstName
            textView.text = name
        }
    }
}

テーブル操作 insert

val user = User(
    1,
    "hoge",
    "fuga"
)
database?.userDao()?.insert(user)

テーブルclose

if(database != null) {
    if(database?.isOpen == true) {
        database?.close()
    }
    database = null
}

マイグレーション操作

Database今回だとAppDatabaseのバージョンを2にする。
テーブルにカラム追加など行う。
Database読み込み時の処理は以下の様にする。

val migration1to2 = object : Migration(1,2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("Alter TABLE User ADD COLUMN test text;")
 }
}
database = Room.databaseBuilder(this, AppDatabase::class.java, "AppDatabase")
.addMigrations(migration1to2)
.build()

お疲れさまでした。