概要
Realmは、オープンソースのモバイル向けオブジェクトデータベース管理システムである。
弊社のモバイルアプリdrillのAndroid版でも、設問の回答やアイデアメモ等のデータをデバイスに保存するために使っている。
Realmで保存しているデータのModelを書き換えるとマイグレーションが必要になる。実施した際に覚えておきたいと思ったところをまとめておく。
手順
マイグレーション用のコードを記述する
マイグレーションするために、RealmMigration
を実装して、migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long)
をオーバーライドする。
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の場合全部記述する)
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
や起動時に実行するコード等に以下を記述する。
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()
を設定する。
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