我的会议室数据库应该从版本0开始吗?

时间:2020-05-27 18:26:07

标签: java android sqlite android-room

我已经意识到我的数据库迁移策略不正确,因此将其重写。现在看起来像这样:

@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();

}

具有如下所示的帮助器类:

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;
    }


}

当我删除数据库并运行应用程序时,第一次访问数据库并没有按预期运行此迁移。相反,我看到SQLLiteOpenHelper.java内的数据库版本为0,试图迁移到2。由于Android helper类的这一特定部分:

                    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();
                    }

getDatabaseLocked方法中,如果从版本0开始,它将不会运行任何迁移,而只是将版本设置为您要迁移到的版本。

这种行为对我来说没有任何意义,所以我认为我错过了一些东西。我尝试了一种变通的解决方法,即仅通过将迁移强制为1(通过创建其他RoomDatabase类)然后运行上述方法即可。我还尝试过手动将数据库版本设置为1,但这似乎也不是正确的解决方案。

让我知道您是否需要更多的上下文代码

1 个答案:

答案 0 :(得分:1)

我不确定我为您解决了麻烦。很抱歉,如果我的回答如下-不是这样。

  • Room是一个使用大量注释的框架,并且在构建过程中会生成大量自动生成的代码。它的一部分-是对SQLite的查询,这些查询应在应用程序启动且找不到任何现有数据库时运行。这些查询是根据实体的结构,索引,外键等形成的。
  • 假设您具有数据库版本1,并且在构建期间生成了一些代码(代码#1),并带有诸如“如果不存在则创建表...”之类的查询。
  • 之后,您对表的结构进行了一些更改,将版本更改为2。在生成期间,生成了另一个代码(代码#2),其中的查询有点不同(包括对表所做的更改)。
  • 您已在版本1的设备应用程序上安装,调用了代码#1-创建了表(如果您不使用资产中的数据库预填充-则创建为空)。您开始用数据填充表,然后-更新到版本2。那时,从MIGRATION_1_2块中调用了代码-为了保存数据并仅通过“特殊”查询更改表的结构。
  • 但是,如果您从设备上卸载了应用程序,然后安装了版本2的应用程序,则将调用代码2来创建版本2的实际表,这是不需要迁移的吗?因此,在这种情况下为“ 0”版本-之前已安装的数据库版本,因为未安装数据库-为0。

我不清楚您希望进行哪种迁移(在“迁移”中,有一些带有一些插入值的块)。如果此迁移的唯一更改是-将一些预定义的值插入到表中-那么也许您应该prepopulate your initial database from assets or from file