从 SQLite 迁移到 Room

Room 持久性库在直接使用 SQLite API 的基础上提供了一些好处

  • SQL 查询的编译时验证
  • 方便的注释,可最大程度地减少重复且容易出错的样板代码
  • 简化的数据库迁移路径

如果您的应用目前使用的是非 Room SQLite 实现,请阅读本页面了解如何将您的应用迁移到使用 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 注解这些字段,表示 Room 不应为其在对应表中创建列。
  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 的更多信息,请参阅以下其他资源。

博客