Обновление базы данных ORMLite - программирование
Подтвердить что ты не робот

Обновление базы данных ORMLite

Я на самом деле разрабатываю приложение, использующее библиотеку ORMLite (что замечательно), но я начинаю использовать его.

У меня есть вопрос об обновлении базы данных внутри устройства.

Скажем, что кто-то загружает мое приложение в Google Play. Спустя несколько месяцев я обязательно заполню несколько таблиц новыми записями.

Когда этот человек выполняет обновление приложения, как я могу просто обновить базу данных новыми записями и сохранить в ней старые.

Чтобы быть более понятным, представьте, что пользователь ответил на вопросы в моем приложении. Когда я буду вводить новые вопросы, как я могу вставить их в db, когда он обновит мое приложение и сохранит вопросы, на которые уже был дан ответ?

4b9b3361

Ответ 1

Когда этот человек выполняет обновление приложения, как я могу просто обновить базу данных новыми записями и сохранить в ней старые.

Идея состоит в том, чтобы использовать номер версии, который передается методу onUpgrade(...). Используя ORMLite, метод OrmLiteSqliteOpenHelper.onUpgrade(...) принимает число oldVersion и newVersion. Затем вы можете записать код преобразования в свое приложение, которое может преобразовывать данные из старого формата и обновлять схему.

Дополнительные сведения см. в документах ORMLite по теме:

http://ormlite.com/docs/upgrade-schema

Чтобы процитировать, вы можете сделать что-то вроде следующего:

if (oldVersion < 2) {
  // we added the age column in version 2
  dao.executeRaw("ALTER TABLE `account` ADD COLUMN age INTEGER;");
}
if (oldVersion < 3) {
  // we added the weight column in version 3
  dao.executeRaw("ALTER TABLE `account` ADD COLUMN weight INTEGER;");
}

Если у вас есть существующие данные, которые нужно преобразовать, вы должны сделать преобразования в SQL, если это возможно.

Другой альтернативой было бы иметь объект Account и объект OldAccount, который указывает на одно и то же имя таблицы. Затем вы можете читать объекты OldAccount, используя oldAccountDao, преобразовать их в объекты Account, а затем обновить их с помощью accountDao обратно в ту же таблицу. Вы должны быть осторожны с кэшами объектов здесь.

Ответ 2

Я делаю так:

@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {

    switch (oldVersion) {
    case 1:
        updateFromVersion1(database, connectionSource, oldVersion, newVersion);
        break;
    case 2:
        updateFromVersion2(database, connectionSource, oldVersion, newVersion);
        break;
    default:
        // no updates needed
        break;
    }

}

private void updateFromVersion1(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    // do some stuff here
    onUpgrade(database, connectionSource, oldVersion + 1, newVersion);
}

private void updateFromVersion2(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    // do some stuff here
    onUpgrade(database, connectionSource, oldVersion + 1, newVersion);
}

Это приведет к постепенному обновлению независимого пользователя db независимо от того, какую версию db он придет.

Ответ 3

Небольшая информация, неясно, есть ли у вас изменения в структуре таблиц.

a) Если вы не измените структуру базы данных.

1 В новой версии вашей программы при запуске проверки ранее сохраненной версии (например, в настройках) с текущим (см. PackageManager.getPackageInfo)

saved = 0 - Пользователь только что установил новую версию

сохранен < current - Пользователь обновляет вашу программу

2 Добавить новые данные на базу

3 Сохранить текущую версию при настройках

b) Если структура таблицы изменилась (добавлены или удалены поля)

1 Увеличьте номер версии вашей базы данных (см. раздел "Расширяет класс OrmLiteSqliteOpenHelper" )

2 Когда пользователь сначала запускается в вашу программу, будет вызван метод 'onUpgrade' (в вашем расширении класс OrmLiteSqliteOpenHelper), который будет передан старым и новым номерам версий.

  • Прочитайте существующие данные в кеше (temp)
  • создать таблицу
  • Добавить данные из кэша + ваши новые данные

Ответ 4

Мне не нравится удалять базу данных при каждом обновлении или писать код обновления после добавления каждого поля, поэтому...

Я пытаюсь сделать это вот так:

@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    ArrayList<String> tableNames = getTableNames(database);
    for (Class clazz : daoClasses) {
        try {
            Annotation annotation = clazz.getAnnotation(DatabaseTable.class);
            if (annotation != null && annotation instanceof DatabaseTable) {
                String tableName = ((DatabaseTable) annotation).tableName();
                if(!tableNames.contains(tableName)){
                    TableUtils.createTable(connectionSource, clazz);
                } else {
                    addColumns(database, tableName, clazz);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

private ArrayList<String> getTableNames(SQLiteDatabase database){
    ArrayList<String> tableNames = new ArrayList<>();
    Cursor cursor = database.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
    if (cursor.moveToFirst()) {
        while ( !cursor.isAfterLast() ) {
            tableNames.add(cursor.getString(0));
            cursor.moveToNext();
        }
    }
    cursor.close();
    return tableNames;
}

private void addColumns(SQLiteDatabase database, String tableName, Class clazz){
    Cursor mCursor = database.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null);
    for (Field field : clazz.getDeclaredFields()) {
        try {
            DatabaseField annotationField = field.getAnnotation(DatabaseField.class);
            if (annotationField != null && !annotationField.foreign()){
                String columnName = field.getName();
                boolean hasColumn = mCursor.getColumnIndex(columnName) != -1;
                if (!hasColumn) {
                    String columnType = field.getType().getSimpleName();
                    if(columnType.equals(String.class.getSimpleName())){
                        columnType = "TEXT";
                    } else {
                        columnType = columnType.toUpperCase();
                    }
                    database.execSQL(MessageFormat.format("ALTER TABLE `{0}` ADD COLUMN {1} {2};", tableName, columnName, columnType));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    mCursor.close();
}

Я надеюсь, что этот код может быть лучше.

Здесь я не удаляю старые таблицы и столбцы, которые были удалены из dao, и я не создаю чужие поля (я не уверен, что мне это нужно).