从 SQLite 迁移到 Room

与直接使用 SQLite API 相比,Room 持久性库具有诸多优势:

  • 针对 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 为这些字段添加注解,以指明 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,请参阅下面列出的其他资源:

博客