从 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 应使用哪个构造函数。
KotlinJava
@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?,
)
@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。

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

定义迁移路径

由于数据库版本号发生了变化,因此您必须定义 Migration 对象以指明迁移路径,以便 Room 保留数据库中的现有数据。 只要数据库架构保持不变,它就可能为空的实现。

KotlinJava
val MIGRATION_1_2 = object : Migration(1, 2) {
 
override fun migrate(database: SupportSQLiteDatabase) {
   
// Empty implementation, because the schema isn't changing.
 
}
}
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 创建一个应用迁移路径的数据库实例:

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

测试实现效果

请务必测试新的 Room 实现:

增量迁移

如果应用使用复杂的大型数据库,则可能无法一次性将应用迁移到 Room。相反,您可以先选择实现数据实体和 Room 数据库,然后在以后将查询方法迁移到 DAO。为此,您可以将自定义数据库帮助程序类替换为您从 RoomDatabase.getOpenHelper() 接收的 SupportSQLiteOpenHelper 对象。

其他资源

如需详细了解如何从 SQLite 迁移到 Room,请参阅下面列出的其他资源:

博客