пятница, 9 января 2015 г.

[ANDROID] SQLite Migration. Миграция баз данных




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


    В большинстве случаев, для этого рекомендуют или дропать таблицы(если данные не критичны) и пересоздавать их, или же писать тонны кода в методе onUpgrade с ALTER TABLE, что как раз мне показалось несколько мерзким :) Если вы работаете в большом проекте, который будет в поддержке не один месяц, год, то спустя какое-то время onUpgrade превратится в сущий ад, километрового кода. Т.е. нужно более компромиссное решение, не сильно напрягающее по написанию кода и позволяющее спокойно отследить версию базы и в какой версии, что было изменено. По этому лучшим решением было написание скрипта для этого дела и парсера для него.

   Особо в детали кода вдаваться не буду, код вы можете посмотреть и сами. Пройдусь по главным моментам моего решения.

   Все решение заключено в классе SQLiteMergerHelper и скрипте находящемся в assets - dbscript.txt(создается в ручную)
       Для начала объявление в onUpgrade. Для этого нам понадобиться одна строчка кода


  @Override
     public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
        SQLiteMergerHelper.getInstance().readScript(context,db,DATABASE_VERSION);
    }

   
 Ну, а далее вся нагрузка переходит на скрипт, по командам которого мы сейчас пройдемся.(Команды и параметры разбиваются символом ":")

1.  VERSION: - первая команда, для идентификации версии базы. Т.к. пользователь может загрузить ваше приложение, потом забить на пару месяцев на него и потом проапдейтить, приложение сразу упадет если мы последовательно не применим все предыдущие изменения в базе, в конечном итоге выйдя на текущую версию. После команды указываем для какой версии базы актуальны изменения.
 VERSION:
 2
 

2.  ADD_COLUMNS: - команда для добавления поля в таблицу. В параметры передаем
"название таблицы: название поля тип"
 ADD_COLUMNS: 
 messages:test_id INTEGER
 

3.  DROP_COLUMNS: - команда для удаления поля из таблицы. Тут параметром будет SQL запрос создания таблицы, из запроса мы исключаем поле от которого нужно избавиться. Второй параметр - имя таблицы, из которой данные будут копированы. Третим - через запятую, название полей которые будем удалять.
"SQL-запрос без поля: название таблицы: название полей для удаления через запятую"
 DROP_COLUMNS:
 CREATE TABLE message(_id...):message:test_id,is_deleted 
 

4.  RENAME_TABLE: - по названию сразу понятно что она делает :)
"текущее название таблицы: желаемое название таблицы"
 RENAME_TABLE:
 message:message2
 

5.  OTHER_QUERY: - команда для исполнения любых SQL-запросов. Этой командой я пользовался не часто, но дело было.
 OTHER_QUERY:
 CREATE TABLE message (_id INTEGER PRIMARY KEY, name TEXT,message TEXT)
 
 Вот и все команды на текущий момент. Для наглядности, вся поддержка версионности базы превращается в несколько строчек в скрипте.



 И так, я избавился от кучи говнокода и проблемой слияния, что желаю и вам :)
 Исходник класса я выложил на github в процессе я его еще доработаю и сделаю проект-пример

Всех с прошедшими праздниками! Не пыльного кода и интересных проектов!  



Комментариев нет :

Отправить комментарий