Миграция помещения не выполняется при сложных изменениях схемы - PullRequest
0 голосов
/ 28 января 2019

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

Имя моей существующей таблицы WordTable

@Entity
data class WordTable(
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,
    var word: String = "",
    var des: String = "",
    var bookmark: Boolean = false,
    var addByUser: Boolean = false,
    var uploaded: Boolean = false)

Iхочу добавить эти два столбца, поэтому мой код теперь

@Entity
data class WordTable(
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,
    var word: String = "",
    var des: String = "",
    var ref: String = "Added by user",
    var recent: Date = Date(),
    var bookmark: Boolean = false,
    var addByUser: Boolean = false,
    var uploaded: Boolean = false)

Примечание: я предоставляю преобразователь даты

Создайте новую таблицу

database.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    " word TEXT," +
                    " des TEXT," +
                    " ref TEXT," +
                    " recent INTEGER," +
                    " bookmark INTEGER," +
                    " addByUser INTEGER," +
                    " uploaded INTEGER)")

Скопируйте предыдущие данные

database.execSQL("Insert Into USER (id, word, des, bookmark, addByUser, uploaded) Select * From WordTable")

Удалить таблицу слов

database.execSQL("Drop Table WordTable")

Переименовать таблицу пользователя в WordTable

database.execSQL("Alter Table USER RENAME TO WordTable")

И я получаю эту ошибку;

Expected:
TableInfo{name='WordTable', columns={addByUser=Column{name='addByUser', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, word=Column{name='word', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, bookmark=Column{name='bookmark', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, uploaded=Column{name='uploaded', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, ref=Column{name='ref', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, des=Column{name='des', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, recent=Column{name='recent', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='WordTable', columns={addByUser=Column{name='addByUser', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, word=Column{name='word', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, bookmark=Column{name='bookmark', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, uploaded=Column{name='uploaded', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, ref=Column{name='ref', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, des=Column{name='des', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, recent=Column{name='recent', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}

разница между ожидаемым и найденным составляет

Expected: notNull=true
Found: notNull=false

, поэтому я пытаюсь изменить код создания таблицы

database.execSQL("CREATE TABLE `USER` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `word` TEXT NOT NULL, `des` TEXT NOT NULL, `ref` TEXT NOT NULL, `recent` INTEGER NOT NULL, `bookmark` INTEGER NOT NULL, `addByUser` INTEGER NOT NULL, `uploaded` INTEGER NOT NULL)")

Но на этот раз я получаю эту ошибку:

android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: USER.ref (Sqlite code 1299), (OS error - 2:No such file or directory)
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:742)

Я также пытаюсь изменить таблицу и столбец, но получаю ту же ошибку.

Как я могу это исправить?

Ответы [ 4 ]

0 голосов
/ 13 августа 2019

Разница между ожидаемым и найденным в вашем сообщении об ошибке заключается в ненулевых ограничениях в вашей таблице.

Если вы хотите, чтобы строки были обнуляемыми, определите их переменные как объекты без значений по умолчанию и создайте конструктор, которыйопределяет необходимые строки.Не создавайте экземпляры значений строк одновременно с созданием переменных!

Если вы хотите, чтобы строки никогда не принимали Null, добавьте NOT NULL в конец строк в вашем запросе SQLite, и вы неизменить класс вашей модели.

0 голосов
/ 28 января 2019

Вам не нужно создавать новую таблицу, создайте метод, например:

  private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
            @Override
            public void migrate(@NonNull SupportSQLiteDatabase database) {
                   database.execSQL("ALTER TABLE `WordTable` ADD COLUMN ref STRING");
            }
        };

, и вызовите метод создания базы данных, например:

Room.databaseBuilder(/*parameter want */).addMigrations(MIGRATION_1_2).allowMainThreadQueries().build();
0 голосов
/ 29 января 2019

Вы можете использовать ALTER TABLE Запрос и просто предоставить миграцию

private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE `table_name` ADD COLUMN `column_name` {type} DEFAULT {defaultValue} NOT NULL");
        }
    };

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

0 голосов
/ 28 января 2019

Вы можете копировать запросы для создания таблиц или изменения таблиц из сгенерированного файла базы данных комнат.

Просто дважды нажмите shift и найдите _Impl.

Ваша проблема связана с NON NULL типами данных в ваших таблицах, вам необходимо указать эти поля как NON NULL и обработать DEFAULT значения, которые должны быть назначены во время переноса комнаты.

...