Android: можно ли использовать один класс SQLiteOpenHelper для нескольких файлов базы данных? - PullRequest
19 голосов
/ 20 ноября 2010

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

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

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

Ответы [ 2 ]

17 голосов
/ 20 ноября 2010

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

public class DBOpenHelper extends SQLiteOpenHelper {

    public DBOpenHelper(Context context, String dbName, int dbVersion) {
        super(context, dbName, null, dbVersion);
    }
...
}
2 голосов
/ 20 ноября 2010

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