SQLite から Room に移行する

Room 永続ライブラリには、SQLite API を直接使用するよりも多くのメリットがあります。

  • SQL クエリのコンパイル時検証
  • 繰り返しが多く間違いを犯しやすいボイラープレート コードを最小限に抑える便利なアノテーション
  • 効率的なデータベース移行パス

現在アプリに SQLite を実装するのに Room 以外を使用している場合は、このページを読み、代わりに Room を使用するようにアプリを移行する方法についてご確認ください。Room がアプリで使用する最初の SQLite 実装である場合は、基本的な使用方法について、Room を使用してローカル データベースにデータを保存するをご覧ください。

移行手順

SQLite の実装を Room に移行する手順は次のとおりです。SQLite の実装で大規模なデータベースや複雑なクエリを使用している場合は、Room に徐々に移行することをおすすめします。増分移行戦略については、増分移行をご覧ください。

依存関係を更新する

アプリで Room を使用するには、アプリの build.gradle ファイルに適切な依存関係を含める必要があります。最新の Room の依存関係については、セットアップをご覧ください。

モデルクラスをデータ エンティティに更新する

Room は、データ エンティティを使用してデータベース内のテーブルを表します。各エンティティ クラスはテーブルを表し、そのテーブル内の列を表すフィールドを持っています。既存のモデルクラスを Room エンティティに更新する手順は次のとおりです。

  1. クラス宣言に @Entity アノテーションを付けて、Room エンティティであることを示します。必要に応じて tableName プロパティを使用し、生成されるテーブルにクラス名と異なる名前を付けるように示すことができます。
  2. 主キーフィールドに @PrimaryKey アノテーションを付けます。
  3. 生成されるテーブルの列のいずれかを、対応するフィールドの名前と異なる名前にする場合は、そのフィールドに @ColumnInfo アノテーションを付け、name プロパティを正しい列名に設定します。
  4. データベースに保持しないフィールドがクラスにある場合は、それらのフィールドに @Ignore アノテーションを付けて、対応するテーブルで Roome がそれらのフィールドの列を作成すべきでないことを示します。
  5. 複数のコンストラクタ メソッドがクラスにある場合は、他のすべてのコンストラクタに @Ignore アノテーションを付けて、Room で使用するコンストラクタを指定します。

Kotlin

@Entity(tableName = "users")
data class User(
  @PrimaryKey
  @ColumnInfo(name = "userid") val mId: String,
  @ColumnInfo(name = "username") val mUserName: String?,
  @ColumnInfo(name = "last_update") val mDate: Date?,
)

Java

@Entity(tableName = "users")
public class User {

  @PrimaryKey
  @ColumnInfo(name = "userid")
  private String mId;

  @ColumnInfo(name = "username")
  private String mUserName;

  @ColumnInfo(name = "last_update")
  private Date mDate;

  @Ignore
  public User(String userName) {
    mId = UUID.randomUUID().toString();
    mUserName = userName;
    mDate = new Date(System.currentTimeMillis());
  }

  public User(String id, String userName, Date date) {
    this.mId = id;
    this.mUserName = userName;
    this.mDate = date;
  }

}

DAO を作成する

Room はデータ アクセス オブジェクト(DAO)を使用して、データベースにアクセスするメソッドを定義します。Room DAO を使用してデータにアクセスするのガイダンスに沿って、既存のクエリメソッドを DAO に置き換えてください。

データベース クラスを作成する

Room の実装では、データベース クラスを使用してデータベースのインスタンスを管理します。データベース クラスは RoomDatabase を拡張して、定義したすべてのエンティティと DAO を参照する必要があります。

Kotlin

@Database(entities = [User::class], version = 2)
@TypeConverters(DateConverter::class)
abstract class UsersDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Java

@Database(entities = {User.class}, version = 2)
@TypeConverters(DateConverter.class)
public abstract class UsersDatabase extends RoomDatabase {
  public abstract UserDao userDao();
}

移行パスを定義する

データベースのバージョン番号が変更されるため、Migration オブジェクトを定義して、Room がデータベース内の既存のデータを保持できるように移行パスを示す必要があります。データベース スキーマが変更されない限り、これは空の実装にできます。

Kotlin

val MIGRATION_1_2 = object : Migration(1, 2) {
  override fun migrate(database: SupportSQLiteDatabase) {
    // Empty implementation, because the schema isn't changing.
  }
}

Java

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
  @Override
  public void migrate(SupportSQLiteDatabase database) {
    // Empty implementation, because the schema isn't changing.
  }
};

Room のデータベース移行パスの詳細については、データベースを移行するをご覧ください。

データベースのインスタンス化を更新する

データベース クラスと移行パスを定義したら、Room.databaseBuilder を使用して、移行パスを適用したデータベースのインスタンスを作成できます。

Kotlin

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

Java

db = Room.databaseBuilder(
          context.getApplicationContext(),
          UsersDatabase.class, "database-name"
        )
          .addMigrations(MIGRATION_1_2).build();

実装をテストする

新しい Room の実装を必ずテストしてください。

増分移行

アプリで大規模かつ複雑なデータベースを使用していると、アプリを一度に Room に移行することは現実的でない場合があります。代わりに、最初のステップとしてデータ エンティティと Room データベースを必要に応じて実装してから、後でクエリメソッドを DAO に移行することもできます。そのためには、カスタムのデータベース ヘルパークラスを、RoomDatabase.getOpenHelper() から受け取った SupportSQLiteOpenHelper オブジェクトに置き換えます。

参考情報

SQLite から Room への移行については、次の参考情報をご覧ください。

ブログ