В этом уроке рассмотрим, как выполняется миграция версий базы данных в Room

 


Полный список уроков курса:


 

Если вы работали со стандартными механизмами SQLite в Android, то вы знаете, что когда вы меняете структуру базы данных, вам необходимо поднимать версию базы данных и писать SQL запросы, которые выполнят обновление.

В Room все точно также. Давайте рассмотрим пример.

 

У нас есть Entity класс работника

@Entity()
public class Employee {

   @PrimaryKey
   public long id;

   public String name;

   public int salary;

}

 

Добавим ему поле birthday

@Entity()
public class Employee {

   @PrimaryKey
   public long id;

   public String name;

   public int salary;

   public long birthday;

}

Теперь при запуске приложения мы в логах увидим ошибку: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number

Room сообщает, что мы решили изменить структуру базы данных, а номер версии не поменяли.

 

Ок, исправляемся, и поднимаем версию базы в Database классе.

@Database(entities = {Employee.class}, version = 2)
public abstract class AppDatabase extends RoomDatabase {
   public abstract EmployeeDao employeeDao();
}

Запускаем приложение и снова ошибка: java.lang.IllegalStateException: A migration from 1 to 2 is necessary. Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables

На этот раз Room говорит, что ему нужна миграция - т.е.SQL запрос, который поменяет структуру базы данных так, чтобы эта структура соответствовала Entity классам. Да, Room пока не умеет самостоятельно определять изменения Entity классов и менять под них структуру базы данных.

 

Либо, как вариант, мы можем использовать fallbackToDestructiveMigration в билдере создания базы:

database = Room.databaseBuilder(this, AppDatabase.class, "database")
       .fallbackToDestructiveMigration()
       .build();

В этом случае миграцию можно не настраивать. Но если при запуске приложения Room увидит, что необходима миграция, то он просто пересоздаст базу в соответствии с новой структурой Entity классов и все данные пропадут. Так себе вариант, особенно с точки зрения пользователя. Он потеряет все свои данные.

 

Давайте сделаем миграцию. Мы в Entity класс Employee добавили новое поле birthday. Соответственно в таблицу Employee нам также надо добавить новое поле birthday.

Создаем объект Migration:

public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
   @Override
   public void migrate(final SupportSQLiteDatabase database) {
       database.execSQL("ALTER TABLE Employee ADD COLUMN birthday INTEGER DEFAULT 0 NOT NULL");
   }
};

В конструкторе указываем старую и новую версию базы. Соответственно, при миграции базы с версии 1 на 2, Room вызовет метод migrate этого Migration объекта и в таблице Employee будет создано новое поле.

В каком именно классе создавать объект MIGRATION_1_2 - дело вкуса. Как вариант, можно в AppDatabase.

 

Осталось передать этот объект в билдер базы.

database = Room.databaseBuilder(this, AppDatabase.class, "database")
       .addMigrations(AppDatabase.MIGRATION_1_2)
       .allowMainThreadQueries()
       .build();

В методе addMigration указываем миграцию.

 

Если миграций несколько, то их можно перечислить через запятую.

.addMigrations(AppDatabase.MIGRATION_1_2, AppDatabase.MIGRATION_2_3, AppDatabase.MIGRATION_3_4)

Если пользователь с первой версии базы обновится на четвертую, то все эти миграции будут выполнены одна за другой.

 В следующем уроке рассмотрим, как написать тест для миграции.


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

- тут можно посмотреть, над какими уроками я сейчас работаю, и о чем будут следующие уроки 




Language

Социальные сети

 

Telegram канал



Android чат в Telegram



Группа ВКонтакте



Страница в Facebook