Reputation: 18
I have realised that my database migration strategy was incorrect and have rewritten it. At the moment it looks like this:
@Database(entities = {SaveData.class, Achievement.class}, version = 2, exportSchema = false)
@TypeConverters(MapConverters.class)
public abstract class AppDatabase extends RoomDatabase {
public abstract SaveDataDAO saveDataDAO();
public abstract AchievementDAO achievementDAO();
}
With a helper class that looks like this:
public class AppDatabaseHelper {
private static AppDatabase db;
private AppDatabaseHelper() {
// static utility
}
private static final Migration MIGRATION_1_2 =
new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
Set<AchievementType> achievementTypes = EnumSet.allOf(AchievementType.class);
String values = achievementTypes.stream().map(AppDatabaseHelper::createRow).collect(Collectors.joining(", "));
String fullQuery = "INSERT OR IGNORE INTO Achievement(name, current, total) VALUES " + values;
database.execSQL(fullQuery);
}
};
private static String createRow(AchievementType achievementType) {
String name = achievementType.name();
int total = achievementType.getTotal();
return String.format("('%s',0,%s)", name, total);
}
public static AppDatabase getDatabase(Context context) {
if (db == null) {
db = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "game")
.addMigrations(MIGRATION_1_2)
.build();
}
return db;
}
}
When I delete the database and run the app, accessing the database for the first time does not run this migration as expected. Instead, I can see that the version of the database inside SQLLiteOpenHelper.java
is 0, attempting to migrate to 2. Because of this specific part of the Android helper class:
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
inside the getDatabaseLocked
method, I can see that it will not run any migrations if it starts at version 0, and will instead just set the version to be whatever you are migrating up to.
This behaviour doesn't make any sense to me, so I assume I am missing something. I have tried a hacky workaround of just forcing the migration to go to 1 (by creating a different RoomDatabase
class) then running the above which works. I have also tried manually setting the database version to be 1, but this doesn't seem to be the right solution either.
Let me know if you need more code for context
Upvotes: 0
Views: 221
Reputation: 5103
I am not sure I've got right your trouble. Sorry if my answer below - it's not the case.
It's not clear for me what kind of migration you expect (in Migration there is some block with insert some values). If the only change in this migration is -inserting some predefining values into some table - then maybe you should prepopulate your initial database from assets or from file?
Upvotes: 1