ป้อนข้อมูลฐานข้อมูลห้องล่วงหน้า

หากต้องการให้แอปเริ่มต้นด้วยฐานข้อมูลที่มีชุดข้อมูลที่เฉพาะเจาะจงโหลดไว้แล้ว คุณสามารถป้อนข้อมูลล่วงหน้าในฐานข้อมูลได้ ใน Room คุณสามารถใช้ API เพื่อป้อนข้อมูลล่วงหน้าในฐานข้อมูลเมื่อเริ่มต้นด้วยเนื้อหาจากไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าในระบบไฟล์ของอุปกรณ์

ป้อนข้อมูลล่วงหน้าจากชิ้นงานแอป

หากต้องการป้อนข้อมูลล่วงหน้าในฐานข้อมูล Room จากไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งอยู่ใน ไดเรกทอรี assets/ ของแอป ให้เรียกใช้createFromAsset ฟังก์ชันจากออบเจ็กต์ RoomDatabase.Builder ก่อนที่จะเรียกใช้ build

Room.databaseBuilder<AppDatabase>(appContext, "sample.db")
    .createFromAsset("database/myapp.db")
    .build()

ฟังก์ชัน createFromAsset รับอาร์กิวเมนต์สตริงที่มีเส้นทางแบบสัมพัทธ์จากไดเรกทอรี assets/ ไปยังไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้า

ป้อนข้อมูลล่วงหน้าจากระบบไฟล์

หากต้องการป้อนข้อมูลล่วงหน้าในฐานข้อมูล Room จากไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งอยู่ในระบบไฟล์ของอุปกรณ์ ยกเว้นไดเรกทอรีassets/ของแอป ให้เรียกใช้ฟังก์ชันcreateFromFileจากออบเจ็กต์RoomDatabase.Builder ก่อนที่จะเรียกใช้build:

Room.databaseBuilder<AppDatabase>(appContext, "sample.db")
    .createFromFile(File("mypath"))
    .build()

ฟังก์ชัน createFromFile รับอาร์กิวเมนต์ File สำหรับไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้า Room จะสร้างสำเนาของไฟล์ที่กำหนดแทนที่จะเปิดไฟล์โดยตรง ดังนั้นตรวจสอบว่าแอปมีสิทธิ์อ่านไฟล์

จัดการการย้ายข้อมูลที่มีฐานข้อมูลที่บรรจุไว้ล่วงหน้า

ไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้ายังสามารถเปลี่ยนวิธีที่ฐานข้อมูล Room จัดการการย้ายข้อมูลสำรองได้ด้วย โดยปกติแล้ว เมื่อเปิดใช้การย้ายข้อมูลแบบทำลายล้าง และ Room ต้องทำการย้ายข้อมูลโดยไม่มีเส้นทางการย้ายข้อมูล Room จะลบ ตารางทั้งหมดในฐานข้อมูลและสร้างฐานข้อมูลที่ว่างเปล่าด้วยสคีมาที่ระบุ สำหรับเวอร์ชันเป้าหมาย อย่างไรก็ตาม หากคุณรวมไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าที่มีหมายเลขเดียวกันกับเวอร์ชันเป้าหมาย Room จะป้อนข้อมูลในฐานข้อมูลที่สร้างขึ้นใหม่ด้วยเนื้อหาของไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าหลังจากทำการย้ายข้อมูลแบบทำลายล้าง

ดูข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลฐานข้อมูล Room ได้ที่หัวข้อ ย้ายข้อมูลฐานข้อมูล Room

ส่วนต่อไปนี้จะแสดงตัวอย่างเล็กน้อยเกี่ยวกับวิธีที่การย้ายข้อมูลทำงานในทางปฏิบัติ

ตัวอย่าง: การย้ายข้อมูลสำรองด้วยฐานข้อมูลที่บรรจุไว้ล่วงหน้า

สมมติว่า

  • แอปของคุณกำหนดฐานข้อมูล Room ในเวอร์ชัน 3
  • อินสแตนซ์ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 2
  • มีไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งเป็นเวอร์ชัน 3
  • ไม่มีเส้นทางการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 2 ไปยังเวอร์ชัน 3
  • เปิดใช้การย้ายข้อมูลแบบทำลายล้าง

// Database class definition declaring version 3.
@Database(entities = [SampleEntity::class], version = 3)
abstract class FallbackAppDatabase : RoomDatabase() {
    // ...
}

fun createFallbackDb(appContext: Context) {
    Room.databaseBuilder<FallbackAppDatabase>(appContext, "sample.db")
        .createFromAsset("database/myapp.db")
        .fallbackToDestructiveMigration()
        .build()
}

สิ่งที่จะเกิดขึ้นในสถานการณ์นี้

  1. เนื่องจากฐานข้อมูลที่กำหนดไว้ในแอปเป็นเวอร์ชัน 3 และอินสแตนซ์ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 2 จึงจำเป็นต้องมีการย้ายข้อมูล
  2. เนื่องจากไม่มีแผนการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 2 ไปยังเวอร์ชัน 3 การย้ายข้อมูลจึงเป็นการย้ายข้อมูลสำรอง
  3. เนื่องจากคุณเรียกใช้ฟังก์ชัน Builder fallbackToDestructiveMigration การย้ายข้อมูลสำรองจึงเป็นการย้ายข้อมูลแบบทำลายล้าง Room จะลบอินสแตนซ์ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์
  4. เนื่องจากมีไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งเป็นเวอร์ชัน 3 Room จะสร้างฐานข้อมูลขึ้นใหม่และป้อนข้อมูลโดยใช้เนื้อหาของไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้า หากไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าเป็นเวอร์ชัน 2 Room จะพิจารณาว่าไฟล์ดังกล่าวไม่ตรงกับเวอร์ชันเป้าหมายและจะไม่ใช้ไฟล์ดังกล่าวสำหรับการย้ายข้อมูลสำรอง

ตัวอย่าง: การย้ายข้อมูลที่ใช้งานได้ด้วยฐานข้อมูลที่บรรจุไว้ล่วงหน้า

สมมติว่าแอปของคุณใช้งานเส้นทางการย้ายข้อมูลจากเวอร์ชัน 2 ไปยังเวอร์ชัน 3

// Database class definition declaring version 3.
@Database(entities = [SampleEntity::class], version = 3)
abstract class ImplementedAppDatabase : RoomDatabase() {
    // ...
}

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

fun createImplementedDb(appContext: Context) {
    Room.databaseBuilder<ImplementedAppDatabase>(appContext, "sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_2_3)
        .build()
}

สิ่งที่จะเกิดขึ้นในสถานการณ์นี้

  1. เนื่องจากฐานข้อมูลที่กำหนดไว้ในแอปเป็นเวอร์ชัน 3 และฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 2 จึงจำเป็นต้องมีการย้ายข้อมูล
  2. เนื่องจากมีเส้นทางการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 2 ไปยังเวอร์ชัน 3, Room จะเรียกใช้ฟังก์ชัน migrate ที่กำหนดไว้เพื่ออัปเดตอินสแตนซ์ฐานข้อมูล ในอุปกรณ์เป็นเวอร์ชัน 3 โดยเก็บรักษาข้อมูลที่มีอยู่ใน ฐานข้อมูลไว้ Room จะไม่ใช้ไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้า เนื่องจาก Room จะใช้ไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าในกรณีของการย้ายข้อมูลสำรองเท่านั้น

ตัวอย่าง: การย้ายข้อมูลหลายขั้นตอนด้วยฐานข้อมูลที่บรรจุไว้ล่วงหน้า

ไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้ายังส่งผลต่อการย้ายข้อมูลที่มีหลายขั้นตอนได้ด้วย พิจารณากรณีต่อไปนี้

  • แอปของคุณกำหนดฐานข้อมูล Room ในเวอร์ชัน 4
  • อินสแตนซ์ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 2
  • มีไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งเป็นเวอร์ชัน 3
  • มีเส้นทางการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 3 ไปยังเวอร์ชัน 4 แต่ไม่มีจากเวอร์ชัน 2 ไปยังเวอร์ชัน 3
  • เปิดใช้การย้ายข้อมูลแบบทำลายล้าง

// Database class definition declaring version 4.
@Database(entities = [SampleEntity::class], version = 4)
abstract class MultiStepAppDatabase : RoomDatabase() {
    // ...
}

val MIGRATION_3_4 = object : Migration(3, 4) {
    override suspend fun migrate(connection: SQLiteConnection) {
        // ...
    }
}

fun createMultiStepDb(appContext: Context) {
    Room.databaseBuilder<MultiStepAppDatabase>(appContext, "sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_3_4)
        .fallbackToDestructiveMigration()
        .build()
}

สิ่งที่จะเกิดขึ้นในสถานการณ์นี้

  1. เนื่องจากฐานข้อมูลที่กำหนดไว้ในแอปเป็นเวอร์ชัน 4 และอินสแตนซ์ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 2 จึงจำเป็นต้องมีการย้ายข้อมูล
  2. เนื่องจากไม่มีเส้นทางการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 2 ไปยังเวอร์ชัน 3 การย้ายข้อมูลจึงเป็นการย้ายข้อมูลสำรอง
  3. เนื่องจากคุณเรียกใช้ฟังก์ชัน Builder fallbackToDestructiveMigration การย้ายข้อมูลสำรองจึงเป็นการย้ายข้อมูลแบบทำลายล้าง Room จะลบอินสแตนซ์ฐานข้อมูลในอุปกรณ์
  4. เนื่องจากมีไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าซึ่งเป็นเวอร์ชัน 3 Room จะสร้างฐานข้อมูลขึ้นใหม่และป้อนข้อมูลโดยใช้เนื้อหาของไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้า
  5. ฐานข้อมูลที่ติดตั้งไว้ในอุปกรณ์เป็นเวอร์ชัน 3 แล้ว เนื่องจากยังต่ำกว่าเวอร์ชันที่กำหนดไว้ในแอป จึงจำเป็นต้องมีการย้ายข้อมูลอีกครั้ง
  6. เนื่องจากมีเส้นทางการย้ายข้อมูลที่ใช้งานได้จากเวอร์ชัน 3 ไปยังเวอร์ชัน 4 Room จะเรียกใช้ฟังก์ชัน migrate ที่กำหนดไว้เพื่ออัปเดตอินสแตนซ์ฐานข้อมูล ในอุปกรณ์เป็นเวอร์ชัน 4 โดยเก็บรักษาข้อมูลที่คัดลอก มาจากไฟล์ฐานข้อมูลที่บรรจุไว้ล่วงหน้าเวอร์ชัน 3 ไว้