Подтвердить что ты не робот

Android: можно ли использовать один класс SQLiteOpenHelper для нескольких файлов базы данных?

В моем приложении используются две базы данных (отдельные файлы). Для обработки этих баз данных я создал два класса Helper, которые расширяют SQLiteOpenHelper, по одному для каждой базы данных.

Теперь я собираюсь добавить третью базу данных и задаться вопросом, нужно ли мне создать еще один класс Helper (и если бы я использовал четвертую и пятую базы данных, мне понадобились бы еще больше классов Helper), или я могу использовать тот же Помощник класс для нескольких баз данных?

Проблема, которую я вижу при попытке использовать только один класс Helper, заключается в том, что я не вижу, как передать имя отдельных файлов базы данных в Helper. В настоящее время имя базы данных жестко закодировано как статическое поле каждого из классов Helper, но если бы у меня был только один класс Helper, мне нужно было бы передавать разные имена в Constructor при создании отдельного помощника объекты; проблема заключается в том, что SQLiteOpenHelper Constructor, по-видимому, вызывается Android только одним параметром: Контекст.

4b9b3361

Ответ 1

Конечно, вы можете. Это всего лишь вопрос вашего класса класса Helper. Вы можете просто передать имя DB в свой конструктор класса Helper (вместе с требуемым экземпляром Context) вместо hardcoding:

public class DBOpenHelper extends SQLiteOpenHelper {

    public DBOpenHelper(Context context, String dbName, int dbVersion) {
        super(context, dbName, null, dbVersion);
    }
...
}

Ответ 2

Вам нужен абстрактный класс, который реализует описанный здесь процесс обновления. Затем вы расширяете этот абстрактный класс для каждой из ваших таблиц. В вашем абстрактном классе вы должны хранить ваши таблицы в некотором роде (список, hardcoded), поэтому, когда 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();
}