简体   繁体   中英

Is it possible to update specific table in locally stored database when I release a new version of the app by using database file

I'm going to make an app that manages the product and bookmark information for each product.

It is being developed using Java, SQLite, and Room. So, the database is stored locally.

Information on products is web-crawled, stored in the Product Table in the app.db file, the file is included in the assets folder and the information is made available to users locally using the createFromAsset() method when the app is distributed. https://developer.android.com/training/data-storage/room/prepopulate

private static AppDatabase create(final Context context) {
    return Room.databaseBuilder(context, AppDatabase.class, DB_NAME)
            .createFromAsset("database/app.db")
            .fallbackToDestructiveMigration()
            .allowMainThreadQueries()
            .build();
}

And if the web crawling result is changed, I will replace the app.db file and distribute the app as an updated version.

I want to update the product information when I release a new version of the app, but I want the bookmark information that the user saved locally to remain.

I think two options, but both has a problem.

  • Save it in the ProductBookmark table of the app.db file, the bookmark information will be deleted if the app.db file is replaced and distributed

  • Manage bookmark information in a completely different database file, there might be a problem because I cannot establish foreign key relationships between different databases.

How should I manage the bookmark information?

You can use a query to update the table or leave the query blank. use addMigrations method to change table

Room.databaseBuilder(context, AppDatabase.class, DB_NAME)
        .createFromAsset("database/app.db")
        .addMigrations(MIGRATION_1_2)
        .allowMainThreadQueries()
        .build();

public static final Migration MIGRATION_1_2 = new Migration(1 , 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("SQL COMMAND TO CHANGE SOMETHING ...");
    }
};

Here is what you need to do:

(The solution suggests that the user's bookmark information is saved in a separate table, let's say product_bookmarks on the same database.)

Let's suppose that the database version on the current version of your app is 2. In the new app version, copy a new prepopulated database file in the assets folder with database version 4. Similarly, change the database version in AppDatabase to 4.

Now, replace your create() method with the following:

private static AppDatabase create(Context context) {
    return Room.databaseBuilder(
            context.getApplicationContext(), AppDatabase.class, DB_NAME)
            .createFromAsset("databases/app.db", new PrepackagedDatabaseCallback() {
                @Override
                public void onOpenPrepackagedDatabase(@NonNull SupportSQLiteDatabase db) {
                    // Use this callback to restore the data back to database created from
                    // the new prepopulated database
                }
            })
            .fallbackToDestructiveMigration()
            .addMigrations(new Migration(2, 3) {
                @Override
                public void migrate(@NonNull SupportSQLiteDatabase database) {
                    // Use this callback to backup user data from product_bookmarks table.
                    // Store the backup in a member variable in AppDatabase class, e.g., 
                    // List<ProductBookmark>
                }
            })
            .build();
}

Here is what would happen when this version of your app will be installed:

  • Since database version in this version of the app is 4 and current version of database file is 2, migration would be required.
  • Since we have added migration implementation from version 2 to 3, migrate() method will be called. Here, you should take backup of user's product bookmark data and store it in a member variable or in a file on device.
  • Since the target version is 4 and there is no migration path from version 3 to 4, it would be a fallback migration.
  • Since fallbackToDestructiveMigration() builder method is called, Room would drop the database instance on user's device.
  • Since there is a prepopulated database having version 4, a new database will be created and populated with the data of the prepopulated database file.
  • Once new database is created with prepopulated data, onOpenPrepackagedDatabase() will be called. Here, you should restore the user's bookmark data to the newly created database.

I haven't tested it myself but you may give it a try and post your feedback here. Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM