Realm Blog

Realm Java 0.86 — 新しいMigration APIの登場!

Realm Javaの最新版をwebサイトMavenリポジトリでリリースしました。

このリリースでは、従来のMigration APIを置き換える新たなMigration APIと、Migrationの際に必要となるデータ変換で使用するDynamic APIを導入しました。

Migration API

マイグレーション(モデル定義の変更にともなう移行処理)では、移行のためのロジックを記述しRealmConfigurationにセットする点に変わりはありませんが、ロジックを記述するためのAPIが刷新されました。

新しいAPIでは、DynamicRealmと呼ばれる新しい種類のRealmインスタンスを操作することでマイグレーションロジックを記述します。

DynamicRealmは、スキーマ情報を変更することを可能にした特殊なRealmですが、データの作成やクエリなどは従来のRealmと同様に行うことができます。

RealmMigration migration = new RealmMigration() {
  @Override
  public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

     // DynamicRealmからは変更可能なスキーマインスタンスを取得できます
     RealmSchema schema = realm.getSchema();

     if (oldVersion == 0) {
        // バージョン1への移行処理
        oldVersion++;
     }

     if (oldVersion == 1) {
        // バージョン2への移行処理
        oldVersion++;
     }
  }
}

// 従来通りRealmConfigurationを作成
RealmConfiguration realmConfig = new RealmConfiguration.Builder(context)
  .schemaVersion(2)
  .migration(migration)
  .build();

クラスやフィールドは名前の文字列で参照が可能です。また、作成や変更はメソッドチェーンで記述することができます。

RealmSchema schema = realm.getSchema();

// nameとageの2つのフィールドを持ったPersonクラスを作成
schema.create("Person")
    .addField("name", String.class)
    .addField("age", int.class);

// 属性を指定してフィールドを作成
schema.get("Person")
    .addField("id", long.class, FieldAttribute.PRIMARY_KEY);

// リンクを追加
schema.get("Person")
    .addRealmObjectField("favoriteDog", schema.get("Dog"))
    .addRealmListField("dogs", schema.get("Dog"));

// マイグレーション中で新たなオブジェクトを作成することも可能
DynamicRealmObject person = realm.createObject("Person");
person.setString("name", "John");

// クラスの削除(クラスに属するオブジェクトも削除されます)
schema.remove("Person");

特定のRealmObjectクラスに対してデータの変換を記述することもできます。これはオブジェクトの型を変更する際や、フィールドの結合や分割の際に威力を発揮します。

schema.get("Person")
  .transform(new RealmObjectSchema.Function() {
    @Override
    public void apply(DynamicRealmObject obj) {
      obj.setInt("age", obj.getInt("age") + 1); // すべてのオブジェクトのageを1増やす
    }
  });

どのような操作が可能かについては、RealmSchemaRealmObjectSchemaのAPIリファレンスを参照してください。 また、migration exampleも新しいAPIに対応するように更新されています。

Dynamic API

新たに導入されるDynamic APIはマイグレーションだけでなく、通常のデータの読み書きにも使用することができます。例えばCSVからのデータの読み込みを記述するといった、コンパイル時にはモデル定義が定まらない処理を実装する際に威力を発揮します。

Dynamic Realmは、従来のRealmインスタンスを取得する際に使用していたRealmConfigurationがそのまま利用できますが、スキーマ定義、スキーマバージョン、マイグレーションロジックは無視されます。

RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build();
DynamicRealm realm = DynamicRealm.getInstance(realmConfig);

// DynamicRealmでは、すべてのオブジェクトはDynamicRealmObjectです
DynamicRealmObject person = realm.createObject("Person");

// すべてのフィールドは名前の文字列でアクセスします
String name = person.getString("name");
int age = person.getInt("age");

// データベースのスキーマは依然として有効なので、スキーマに違反する操作には例外がスローされます
person.getString("I don't exist");

// クエリは従来通り使用可能です
RealmResults<DynamicRealmObject> persons = realm.where("Person").equalTo("name", "John").findAll();

DynamicRealmは柔軟性のために型安全とパフォーマンスを犠牲にしています。DynamicRealmが提供する柔軟性がどうしても必要な場合でのみ使うようにしてください。

#enumsmatter

クエリAPIでは、SortCaseを指定する際、従来のbooleanではなくenumを使うように変更されています。 この変更で、より可読性が高く型安全なコードが記述できるようになります。

realm.where(Person.class)
  .beginsWith("name", "John", Case.INSENSITIVE)
  .findAllSorted("name", Sort.ASCENDING)

変更の一覧はchangelogを参照してください。


Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

記事の更新情報を受け取る