Обновление данных приложения Android с несколькими таблицами (без уничтожения незатронутых таблиц) - PullRequest
3 голосов
/ 28 сентября 2011

В моем приложении для Android; У меня есть одна база данных с несколькими таблицами. Каждая таблица более или менее отделена друг от друга, но рассчитана (для лучшей практики?) Только на один файл БД.

Когда дело доходит до обновлений, это в настоящее время дело "все или ничего". При обновлении он «УДАЛЯЕТ» все таблицы и воссоздает их. Однако это довольно резко, если изменилась только одна из таблиц, поскольку данные всех других таблиц также потеряны.

Есть ли встроенный способ автоматического обновления только тех таблиц, которые изменились? (например, используя номер версии для / таблицы?)

Если нет, то я вижу два варианта:

  1. Используйте отдельные базы данных / файлы для каждой таблицы, чтобы использовать встроенную функцию обновления версии.

  2. Используйте номер версии базы данных, чтобы узнать, когда изменилась «схема», но иметь отдельную таблицу для хранения текущих TABLE_VERSIONS и управлять моим собственным обновлением, проверяя номер версии каждой таблицы по текущей сборке и DROP. / CREATE Таблицы, где это необходимо.

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

Ответы [ 2 ]

1 голос
/ 28 сентября 2011

Если вы используете вспомогательные классы Android SQLite (например, SQLiteOpenHelper), то у вас есть только один номер версии, представляющий схему базы данных.Лично я помещаю весь код создания схемы в свой экземпляр SQLiteOpenHelper и сохраняю логику обновления простой:

@Override
public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {

    // Alter all the tables so the schema is brought up-to-date.
    if (oldVersion < newVersion) {
        db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER NOT NULL");
    }
}
1 голос
/ 28 сентября 2011

Вам нужен абстрактный класс, который реализует процесс обновления, описанный здесь. Затем вы расширяете этот абстрактный класс для каждой из ваших таблиц. В вашем абстрактном классе вы должны хранить свои таблицы таким образом (список, жестко закодированный), чтобы при запуске onUpgrade вы перебирали элементы таблицы и для каждого элемента таблицы выполняли описанные шаги. Они будут модернизированы, сохраняя все существующие детали. Обратите внимание, что событие onUpgrade запускается только один раз для каждой базы данных, поэтому вам нужно выполнить итерации по всем вашим таблицам, чтобы обновить все из них. Вы поддерживаете только 1 номер версии для всей базы данных.

  • BeginTransaction
  • запустить создание таблицы с помощью if not exists (мы проводим обновление, поэтому таблица может еще не существовать, она не сможет изменить и удалить)
  • внести в список существующие столбцы List<String> columns = DBUtils.GetColumns(db, TableName);
  • таблица резервных копий (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • создать новую таблицу (новейшая схема создания таблицы)
  • получить пересечение с новыми столбцами, на этот раз столбцы взяты из обновленной таблицы (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • восстановление данных (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • удалить таблицу резервных копий (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

(Это не обрабатывает понижение таблицы, если вы переименуете столбец, вы не передадите существующие данные, поскольку имена столбцов не совпадают).

.

public static List<String> GetColumns(SQLiteDatabase db, String tableName) {
    List<String> ar = null;
    Cursor c = null;
    try {
        c = db.rawQuery("select * from " + tableName + " limit 1", null);
        if (c != null) {
            ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
        }
    } catch (Exception e) {
        Log.v(tableName, e.getMessage(), e);
        e.printStackTrace();
    } finally {
        if (c != null)
            c.close();
    }
    return ar;
}

public static String join(List<String> list, String delim) {
    StringBuilder buf = new StringBuilder();
    int num = list.size();
    for (int i = 0; i < num; i++) {
        if (i != 0)
            buf.append(delim);
        buf.append((String) list.get(i));
    }
    return buf.toString();
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...