Điền sẵn cơ sở dữ liệu Room của bạn

Đôi khi, bạn có thể muốn ứng dụng của mình khởi động bằng cơ sở dữ liệu đã được tải sẵn một tập dữ liệu cụ thể. Quá trình này được gọi là điền sẵn cơ sở dữ liệu. Trong Room 2.2.0 trở lên, bạn có thể dùng các phương thức API để điền sẵn cơ sở dữ liệu Room khi khởi động bằng nội dung từ tệp cơ sở dữ liệu đóng gói sẵn trong hệ thống tệp của thiết bị.

Điền sẵn từ tài sản ứng dụng

Để điền sẵn cơ sở dữ liệu Room từ tệp cơ sở dữ liệu đóng gói sẵn nằm ở bất cứ đâu trong thư mục assets/ của ứng dụng, hãy gọi phương thức createFromAsset() từ đối tượng RoomDatabase.Builder của bạn trước khi gọi build():

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build();

Phương thức createFromAsset() chấp nhận một đối số chuỗi chứa đường dẫn tương đối từ thư mục assets/ đến tệp cơ sở dữ liệu đóng gói sẵn.

Điền sẵn từ hệ thống tệp

Để điền sẵn cơ sở dữ liệu Room từ tệp cơ sở dữ liệu đóng gói sẵn nằm ở bất cứ đâu trong hệ thống tệp của thiết bị ngoại trừ thư mục assets/ của ứng dụng, hãy gọi phương thức createFromFile() từ đối tượng RoomDatabase.Builder của bạn trước khi gọi build():

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromFile(File("mypath"))
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromFile(new File("mypath"))
    .build();

Phương thức createFromFile() chấp nhận một đối số File cho tệp cơ sở dữ liệu đóng gói sẵn. Room sẽ tạo bản sao của tệp được chỉ định thay vì mở trực tiếp, do đó, hãy đảm bảo ứng dụng của bạn có quyền đọc tệp đó.

Xử lý các hoạt động di chuyển chứa cơ sở dữ liệu đóng gói sẵn

Tệp cơ sở dữ liệu đóng gói sẵn cũng có thể thay đổi cách cơ sở dữ liệu Room xử lý hoạt động di chuyển dự phòng. Thông thường, khi bật tuỳ chọn di chuyển phá bỏ và Room phải thực hiện hoạt động di chuyển mà không có lộ trình di chuyển, Room sẽ bỏ mọi bảng trong cơ sở dữ liệu và tạo cơ sở dữ liệu trống bằng giản đồ đã chỉ định cho phiên bản mục tiêu. Tuy nhiên, nếu bạn thêm một tệp cơ sở dữ liệu đóng gói sẵn có cùng số với phiên bản mục tiêu, thì Room sẽ tìm cách điền sẵn cơ sở dữ liệu mới tạo lại bằng nội dung của tệp cơ sở dữ liệu đóng gói sẵn sau khi thực hiện hoạt động di chuyển phá bỏ.

Để biết thêm thông tin về hoạt động di chuyển cơ sở dữ liệu Room, hãy xem bài viết Di chuyển cơ sở dữ liệu Room.

Các phần sau đây trình bày một số ví dụ về cách thức di chuyển trong thực tế.

Ví dụ: Di chuyển dự phòng bằng cơ sở dữ liệu đóng gói sẵn

Hãy giả định những điều sau:

  • Ứng dụng của bạn xác định cơ sở dữ liệu Room trên phiên bản 3.
  • Thực thể cơ sở dữ liệu đã cài đặt trên thiết bị đang ở phiên bản 2.
  • Có một tệp cơ sở dữ liệu đóng gói sẵn ở phiên bản 3.
  • Không có lộ trình di chuyển được triển khai từ phiên bản 2 sang phiên bản 3.
  • Đã bật tuỳ chọn di chuyển phá bỏ.

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build();

Dưới đây là những gì sẽ xảy ra trong tình huống này:

  1. Vì cơ sở dữ liệu đã xác định trong ứng dụng của bạn là phiên bản 3 và thực thể cơ sở dữ liệu đã cài đặt trên thiết bị đang ở phiên bản 2, nên bạn cần thực hiện hoạt động di chuyển.
  2. Do không có kế hoạch di chuyển được triển khai từ phiên bản 2 sang phiên bản 3, nên hoạt động di chuyển sẽ là di chuyển dự phòng.
  3. Do phương thức tạo fallbackToDestructiveMigration() được gọi nên hoạt động di chuyển dự phòng sẽ mang tính phá bỏ. Room sẽ bỏ thực thể cơ sở dữ liệu được cài đặt trên thiết bị.
  4. Do có một tệp cơ sở dữ liệu đóng gói sẵn ở phiên bản 3, nên Room sẽ tạo lại cơ sở dữ liệu và điền sẵn cơ sở dữ liệu này bằng nội dung của tệp cơ sở dữ liệu đóng gói sẵn. Mặt khác, nếu tệp cơ sở dữ liệu đóng gói sẵn của bạn ở phiên bản 2, thì Room sẽ lưu ý rằng tệp không khớp với phiên bản mục tiêu và sẽ không dùng tệp này trong quá trình di chuyển dự phòng.

Ví dụ: Di chuyển được triển khai bằng cơ sở dữ liệu đóng gói sẵn

Hãy giả định rằng ứng dụng của bạn triển khai lộ trình di chuyển từ phiên bản 2 sang phiên bản 3:

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 2 to version 3.
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 2 to version 3.
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build();

Dưới đây là những gì sẽ xảy ra trong tình huống này:

  1. Vì cơ sở dữ liệu đã xác định trong ứng dụng của bạn là phiên bản 3 và cơ sở dữ liệu đã cài đặt trên thiết bị đang ở phiên bản 2, nên bạn cần thực hiện hoạt động di chuyển.
  2. Do có lộ trình di chuyển được triển khai từ phiên bản 2 sang phiên bản 3, nên Room sẽ chạy phương thức migrate() đã xác định để cập nhật thực thể cơ sở dữ liệu trên thiết bị lên phiên bản 3, giúp duy trì dữ liệu đã có trong cơ sở dữ liệu. Room không dùng tệp cơ sở dữ liệu đóng gói sẵn vì Room chỉ dùng tệp cơ sở dữ liệu đóng gói sẵn khi di chuyển dự phòng.

Ví dụ: Di chuyển nhiều bước bằng cơ sở dữ liệu đóng gói sẵn

Tệp cơ sở dữ liệu đóng gói sẵn cũng có thể ảnh hưởng đến hoạt động di chuyển bao gồm nhiều bước. Hãy xem xét trường hợp sau:

  • Ứng dụng của bạn xác định cơ sở dữ liệu Room trên phiên bản 4.
  • Thực thể cơ sở dữ liệu đã cài đặt trên thiết bị đang ở phiên bản 2.
  • Có một tệp cơ sở dữ liệu đóng gói sẵn ở phiên bản 3.
  • Có lộ trình di chuyển được triển khai từ phiên bản 3 sang phiên bản 4, nhưng không có lộ trình di chuyển từ phiên bản 2 sang phiên bản 3.
  • Đã bật tuỳ chọn di chuyển phá bỏ.

Kotlin

// Database class definition declaring version 4.
@Database(version = 4)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 3 to version 4.
val MIGRATION_3_4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 4.
@Database(version = 4)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 3 to version 4.
static final Migration MIGRATION_3_4 = new Migration(3, 4) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build();

Dưới đây là những gì sẽ xảy ra trong tình huống này:

  1. Vì cơ sở dữ liệu đã xác định trong ứng dụng của bạn là phiên bản 4 và thực thể cơ sở dữ liệu đã cài đặt trên thiết bị đang ở phiên bản 2, nên bạn cần thực hiện hoạt động di chuyển.
  2. Do không có lộ trình di chuyển được triển khai từ phiên bản 2 sang phiên bản 3, nên hoạt động di chuyển sẽ là di chuyển dự phòng.
  3. Do phương thức tạo fallbackToDestructiveMigration() được gọi nên hoạt động di chuyển dự phòng sẽ mang tính phá bỏ. Room sẽ bỏ thực thể cơ sở dữ liệu trên thiết bị.
  4. Do có một tệp cơ sở dữ liệu đóng gói sẵn ở phiên bản 3, nên Room sẽ tạo lại cơ sở dữ liệu và điền sẵn cơ sở dữ liệu này bằng nội dung của tệp cơ sở dữ liệu đóng gói sẵn.
  5. Cơ sở dữ liệu đã cài đặt trên thiết bị hiện ở phiên bản 3. Vì phiên bản này vẫn thấp hơn phiên bản đã xác định trong ứng dụng của bạn, nên bạn cần thực hiện hoạt động di chuyển khác.
  6. Do có lộ trình di chuyển được triển khai từ phiên bản 3 sang phiên bản 4, nên Room sẽ chạy phương thức migrate() đã xác định để cập nhật thực thể cơ sở dữ liệu trên thiết bị lên phiên bản 4, giúp duy trì dữ liệu đã sao chép từ tệp cơ sở dữ liệu đóng gói sẵn ở phiên bản 3.

Tài nguyên khác

Để tìm hiểu thêm về cách điền sẵn cơ sở dữ liệu Room, hãy xem các tài nguyên bổ sung sau đây.

Video

Blog