11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AndroidアプリでRealmマイグレーションするときの勘所

Posted at

概要

Realmは、オープンソースのモバイル向けオブジェクトデータベース管理システムである。
弊社のモバイルアプリdrillのAndroid版でも、設問の回答やアイデアメモ等のデータをデバイスに保存するために使っている。
Realmで保存しているデータのModelを書き換えるとマイグレーションが必要になる。実施した際に覚えておきたいと思ったところをまとめておく。

手順

マイグレーション用のコードを記述する

マイグレーションするために、RealmMigrationを実装して、migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long)をオーバーライドする。

MyMigration.kt
class MyMigration : RealmMigration {
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        // Migration code here
    }
}

migrateの内容には、Modelの変更箇所を記述する。
下記に一例を示す。

.create(<新しいモデル名>)

新たに追加したModelがあるときにRealmにModelを作る

.get(<該当モデル名>)

既存のModelに変更があるときにRealmからModelを取得する

.addField(<プロパティ名>, <プロパティの型>, <アノテーション(ある場合)>)

Modelにプロパティを追加する(新規Modelの場合全部記述する)

MyMigration.kt
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        val realmSchema = realm.schema // Realmのスキーマ
        var oldVersion = oldVersion

        if (oldVersion == 0L) { // スキーマのバージョンが以前のものであるとき
            realmSchema.create("NewModel") // NewModelを新規作成した
                .addField("id", Long::class.java, FieldAttribute.PRIMARY_KEY) // @PrimaryKeyアノテーション付きのプロパティ
                .addField("text", String::class.java, FieldAttribute.REQUIRED) // nullを許容しない場合、REQUIREDが必要らしい(ソースがない……)
                .addField("bool", Boolean::class.java)
            realmSchema.get("ExistModel")!! //  ExistModelにプロパティを追加した
                .addField("id", Long::class.javaObjectType) // class.javaObjectTypeはnullを許容する
                .addField("text", String::class.javaObjectType)
            oldVersion++ // マイグレーションしたためスキーマバージョンを上げる
        }
    }

マイグレーションするコードを記述する

マイグレーション用のコードが記述できたら、マイグレーションを実行するコードを記述してマイグレーションする。
MainActivityや起動時に実行するコード等に以下を記述する。

MainActivity.kt
        Realm.init(this)
        val realmConfig = RealmConfiguration.Builder() // Realmの設定を定義
            .schemaVersion(1L) // 新しいスキーマのバージョンを設定
            .migration(MyMigration()) // マイグレーション用のコードを設定
            .build()
        Realm.setDefaultConfiguration(realmConfig) // 上記の設定をRealmにセット

これで、(スキーマのバージョンが0のとき)マイグレーションが実行される。

さらにModelに変更があった場合、MyMigrationに追記し、schemaVersionを上げることで適宜マイグレーションできる。

その他

deleteRealmIfMigrationNeeded()を使う

開発時にModelが頻繁に変わる場合などに、その都度マイグレーションを追記するのは大変であるため、deleteRealmIfMigrationNeeded()を使うことで、マイグレーションせずに開発を続行できる。
realmConfigの定義時にマイグレーション設定の代わりに.deleteRealmIfMigrationNeeded()を設定する。

MainActivity.kt
        val realmConfig = RealmConfiguration.Builder()
            .deleteRealmIfMigrationNeeded()
            .build()

マイグレーションせずにビルドした場合

以下のようなRealmの例外が発生した。

io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:
   - Class 'NewModel' has been added.
   - Property 'ExistModel.id' has been added.
   - Property 'ExistModel.text' has been added.

参考

https://realm.io/docs/java/latest
https://realm.io/docs/java/latest/api/io/realm/RealmMigration.html
https://qiita.com/kumas/items/c98f1006776ad141d5f7

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?