从SQLite迁移到Room

Room 持久性库提供了许多比直接使用 SQLite API 更多的优势

  • SQL 查询的编译时验证
  • 减少重复和易错样板代码的便捷注释
  • 简化的数据库迁移路径

如果您的应用目前使用的是非 Room 的 SQLite 实现,请阅读此页面以了解如何将您的应用迁移到使用 Room。如果您在应用中使用的第一个 SQLite 实现是 Room,请参阅 使用 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 的更多信息,请参阅以下其他资源

博客