Исключение комнаты в таблице: предварительно упакованная база данных имеет недопустимую схему - PullRequest
0 голосов
/ 28 мая 2020

Моя задача - перенести текущую архитектуру нашего приложения (с использованием Cupboard) в Room, и я сталкиваюсь с некоторыми проблемами в самой первой части работы, которая заключается в переносе объектов базы данных, записанных в Java на данный момент (Cupboard поддерживает только Java), чтобы они работали с Room. Это пример:

public class ItemDb {

public Long _id;
public String type;
public String subtype;
public long scheduledTime;
public int iteration;
public String data1;
public String data2;
public String data3;

и вот как это выглядит в базе данных:

enter image description here

То, что я сделано с этим entity создает класс @Entity в Kotlin для использования в Room, и это выглядит так:

@Entity(tableName = "ItemDb")
data class ItemDb(
        @PrimaryKey(autoGenerate = true)
        val _id: Long? = 0,
        val type: String,
        val subtype: String,
        val scheduledTime: Long,
        val iteration: Int,
        val data1: String? = null,
        val data2: String? = null,
        val data3: String? = null
)

Всякий раз, когда я пытаюсь запросить базу данных, я получаю это исключение:

Предварительно упакованная база данных имеет недопустимую схему: ItemDb (com.example.room.model.items.ItemDb). Ожидается: TableInfo {name = 'ItemDb', columns = {duledTime = Column {name ='duledTime ', type =' INTEGER ', affinity =' 3 ', notNull = true, primaryKeyPosition = 0, defaultValue =' null '}, подтип = столбец {name = 'subtype', type = 'TEXT', affinity = '2', notNull = true, primaryKeyPosition = 0, defaultValue = 'null'}, data3 = Column {name = 'data3', type = ' ТЕКСТ ', affinity =' 2 ', notNull = false, primaryKeyPosition = 0, defaultValue =' null '}, data2 = Column {name =' data2 ', type =' TEXT ', affinity =' 2 ', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'}, data1 = Column {name = 'data1', type = 'TEXT', affinity = '2', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'}, итерация = Столбец {name = 'итерация', type = 'INTEGER', affinity = '3', notNull = true, primaryKeyPosition = 0, defaultValue = 'null'}, _id = Column {name = '_ id', type = 'INTEGER' , affinity = '3', notNull = false, primaryKeyPosition = 1, defaultValue = 'null'}, type = Column {name = 'type', type = 'TEXT', affinity = '2', notNull = true, primaryKeyPosition = 0, defaultValue = 'null'}}, foreignKeys = [], индексы = []} Найдено: TableInfo {name = 'ItemDb', columns = {duledTime = Column {name ='duledTime ', type =' INTEGER ', affinity =' 3 ', notNull = false, primaryKeyPosition = 0, defaultValue =' null '}, subtype = Column {name =' subtype ', type =' TEXT ', affinity =' 2 ', notNull = false, primaryKeyPosition = 0, defaultValue =' null '}, data3 = Column {name =' data3 ', type = 'TEXT', affinity = '2', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'}, data2 = Column {name = 'data2', type = 'TEXT', affinity = '2', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'}, data1 = Column {name = 'data1', type = 'TEXT', affinity = '2', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'} , iteration = Column {name = 'iteration', type = 'INTEGER', affinity = '3', notNull = false, primaryKeyPosition = 0, defaultValue = 'null'}, _id = Column {name = '_ id', type = 'integer', affinity = '3', notNull = false, primaryKeyPosition = 1, defaultValue = 'null'}, type = Column {name = 'type', type = 'TEXT', affinity = '2', notNull = false , primaryKeyPosition = 0, defaultValue = 'null'}}, foreignKeys = [], ind ices = []}

Сравнивая два, я вижу, что некоторые поля должны быть помечены notNull, но они, кажется, помечены nullable вместо , хотя класс Kotlin объявляет поля как notNull, избегая использования обнуляемых ?.

Что я делаю не так? Если вам нужна дополнительная информация об архитектуре базы данных, я могу легко их предоставить. Спасибо!

1 Ответ

1 голос
/ 29 мая 2020

В сообщении об ошибке «ожидаемая» схема - это то, что Room создало из вашего Kotlin объявления ItemDb. Он правильно показывает type, subType, scheduledTime и iteration как ненулевые столбцы, а все остальные допускают значение NULL.

Я не использовал Cupboard и предполагаю, что он создает базу данных из вашего ItemDb Java декларация. Схема "found", которая сообщает схему для предварительно упакованной базы данных Cupboard, указывает, что, когда Cupboard создавал базу данных, все столбцы были объявлены допускающими значение NULL (т.е. без NOT NULL).

Чтобы использовать предварительно упакованную базу данных, вы должны необходимо выполнить шаг миграции , который создаст новую таблицу с NOT NULL, указанным для соответствующих полей. Затем вам нужно скопировать все строки из таблицы ItemDb в предварительно упакованной базе данных в новую таблицу с некоторыми переименованиями таблиц (см. Пример ниже).

Оператор создания для новой таблицы будет чем-то например:

CREATE TABLE new_ItemDb (_id INTEGER PRIMARY KEY AUTOINCREMENT,
    type INTEGER NOT NULL, subType INTEGER NOT NULL, scheduledTime INTEGER NOT NULL,
    iteration INTEGER NOT NULL, data1 TEXT, data2 TEXT, data3 TEXT)

Операции миграции можно смоделировать после того, как этот пример скопирован из документации по миграции :

// Migration from 2 to 3, Room 2.2.0
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("""
                CREATE TABLE new_Song (
                    id INTEGER PRIMARY KEY NOT NULL,
                    name TEXT,
                    tag TEXT NOT NULL DEFAULT ''
                )
                """.trimIndent())
        database.execSQL("""
                INSERT INTO new_Song (id, name, tag)
                SELECT id, name, tag FROM Song
                """.trimIndent())
        database.execSQL("DROP TABLE Song")
        database.execSQL("ALTER TABLE new_Song RENAME TO Song")
    }
}

Перед тем, как тратить время на создание кода изменения, описанные выше, вы можете подтвердить мой анализ, временно изменив свое Kotlin определение ItemDb, чтобы все поля были обнуляемыми, а затем повторить попытку использования предварительно упакованной базы данных. Я ожидаю, что импорт будет успешным.

...