I added a new migration to my app (in which I inserted in a table) and uploaded to Google Play (latest update). In MIGRATION_7_8 I added these INSERTs to Types table. When I install it from Google Play (new fresh install) the insterts won't be in the app. But I checked if someone updated the uapp from the previous version in Google Play to the latest version the INSERTs are in the app. That's very interesting... What is triggering on Google Play update what is not triggered on first install?
Now the problem is, that who had updated the app has thses INSERTs but who installs it for the first time they won't have these INSERTs. I tried some ways but nothing worked. Any idea?
@Database(entities = {Types.class, Item.class, Most.class}, version = 8, exportSchema = true)
...
Room.databaseBuilder(context.getApplicationContext(),
MyDatabase.class, "mydatabase.db")
.allowMainThreadQueries()
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4,
MIGRATION_4_5, MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8)
.addCallback(roomCallback)
.build();
Migrations do not run for new installs.
New installs receive the current version of the DB schema/tables without any need to migrate.
Before the Room annotation framework, most Android developers implemented SQL more directly using a class called SQLLiteOpenHelper
, the class that Room it based on.
SQLLiteOpenHelper
has 2 important methods:
// Method is called during creation of the database
@Override
public void onCreate(SQLiteDatabase database) {
...
database.execSQL(DATABASE_CREATE); // Crate the DB in SQL
populateDb(); // Add any necessary data
}
// Method is called during an upgrade of the database
@Override
public void onUpgrade(SQLiteDatabase database,int oldVersion,int newVersion){
Log.w(MyDatabaseHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion);
performUpgrade(db, upgradedVersion, newVersion);
}
// Helper method to upgrade the DB
private int performUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Usually implemented as large switch statement with one case statement for
// each migration. In other words, 1 case statement for each DB version
// (1,2, 3, .... n)
//
// A typical implementation would recursively call performUpgrade until all the
// individual migration cases have been run
//
// Typical migration case:
// 1. Add a new table or add a new column to an existing table
// 2. Add some data to the new table or column when necessary
}
Getting back to Room, when a new user installs the DB, the DB is created under the hood using SQL statements like CREATE TABLE
based on the annotations that have been put on the Room entities. (The onCreate
case)
However, if someone is migrating from DB version 1 to 2 for example, we cannot re-create the table because the data will be lost. In this case, the migration statements like ALTER TABLE x ADD COLUMN y
are run to modify the existing table. (The onUpgrade
case)
With regards to adding new data, yes it needs to be added both when the database is created and when it is migrated/upgraded. New users get all the data they need when the DB is created. But existing users, will in some cases need to receive data when a table or column is added. Duplication of code can usually be avoided by calling the same functions in both cases.
Update: A Nice post showing the relationship between Room and the underlying events methods on the platform:
Does Android Room offer SqliteOpenHelper onCreate() & onUpdate() alternative?