從 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. 如果類別含有多個建構函式方法,請指出 Room 應該使用哪一個建構函式,方法是使用 @Ignore 將所有其他建構函式加上註解。

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,請參閱下列其他資源:

網誌