Должна ли моя база данных номеров начинаться с версии 0? - PullRequest
0 голосов
/ 27 мая 2020

Я понял, что моя стратегия миграции базы данных неверна, и переписал ее. На данный момент это выглядит так:

@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. Из-за этого c часть вспомогательного класса Android:

                    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, а вместо этого просто установит версию, на которую вы мигрируете.

Это поведение не имеют какой-то смысл для меня, поэтому я предполагаю, что что-то упускаю. Я пробовал хитрый обходной путь, просто принудительно переходя с go на 1 (путем создания другого класса RoomDatabase), а затем запускал вышеуказанный, который работает. Я также пробовал вручную установить версию базы данных равной 1, но это тоже не кажется правильным решением.

Сообщите мне, если вам понадобится больше кода для контекста

1 Ответ

1 голос
/ 28 мая 2020

Я не уверен, что правильно понял вашу проблему. Извините, если мой ответ ниже - это не так.

  • Room - это фреймворк, который использует множество аннотаций и во время процесса сборки производит много автоматически сгенерированного кода. Его часть - это запросы к SQLite, которые должны запускаться при запуске приложения и не находят ни одной существующей базы данных. Эти запросы формируются на основе структуры сущностей, индексов, внешних ключей и так далее.
  • Допустим, у вас была версия базы данных 1, и во время сборки был сгенерирован некоторый код (код # 1) с запросами типа «СОЗДАТЬ ТАБЛИЦУ, ЕСЛИ НЕ СУЩЕСТВУЕТ ...».
  • После этого вы сделали некоторые изменения в структуре таблиц, изменена версия на 2. Во время сборки был сгенерирован другой код (код # 2) с немного другими запросами (включая изменения, которые вы внесли в таблицы).
  • Вы установили в приложении устройства с версией 1 был вызван код №1 - были созданы таблицы (если вы не использовали предварительное заполнение базы данных из активов - она ​​была создана пустой). Вы начинаете заполнять таблицы данными, а затем - обновляетесь до версии 2. При этом был вызван код из вашего блока MIGRATION_1_2 - для того, чтобы сохранить ваши данные и просто изменить структуру таблиц с помощью «специального» запроса.
  • Но если вы удалили приложение с устройства, а затем установили приложение с версией 2, ваш код № 2 будет вызываться для создания таблиц, актуальных для версии 2, нет необходимости в миграции, не так ли? Итак, «0» версия в данном случае - версия базы данных, установленной ранее, поскольку база данных не была установлена ​​- это 0.

Мне непонятно, какой тип миграции вы ожидаете это какой-то блок со вставкой некоторых значений). Если единственное изменение в этой миграции - вставка некоторых предопределенных значений в какую-то таблицу - тогда, возможно, вам следует предварительно заполнить исходную базу данных из ресурсов или из файла ?

...