Способ создания таблиц в комнате - PullRequest
0 голосов
/ 16 декабря 2018

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

room.createTable(User::class)

Подобный метод существует, например, в OrmLite

TableUtils.createTable(connectionSource, User::class.java)

Необходимость заключается в сложности создания таблиц с помощью простого SQLite запрос.В настоящее время вы можете написать в своем migrate сценарии create SQLite

db.execSQL("CREATE TABLE IF NOT EXIST `User` (uid INTEGER NON NULL, PRYMARY KEY (`uid`))")

В вышеприведенном методе нет проблем, но он становится сложным и длинным SQLite скрипт, если у вас есть, например, 50 полей.Очевидно, что вы не пишете это самостоятельно, и есть два способа получить Create Script , автоматически сгенерированный для вас Room, чтобы вы просто скопировали прошлое.

  1. После сборки приложения будет сгенерировано AppDatabase_Impl, в котором будут все необходимые создания таблиц.Вы можете получить запрос оттуда
  2. Вы включите exportSchema = true в свою аннотацию @Database, и она создаст versionNumber.json схему базы данных Room в вашей папке схем.Вы можете получить сценарий создания оттуда.

Но оба вышеуказанных метода потребуют от вас запустить приложение без какой-либо надлежащей миграции (поскольку вы не знаете правильный запрос), и оно определенно авария .И после этого у вас есть правильный запрос, который вы можете включить в свой метод миграции.Я думаю, что это не "профессиональный" способ сделать это.Кроме того, даже после того, как вы получите длинный запрос SQLite , он не PR дружественный и не просто хорошая практика иметь длинный запрос SQLite , который не может быть легко отлажен.

Итак, я хотел создать объектно-ориентированный способ создания таблиц при переносе.Единственный подход, который я мог придумать, это, очевидно, использование класса данных модели и создание запроса в соответствии с каждым полем модели.Предположительно, это будет выглядеть так:

fun createTable(db: SupportSQLiteDatabase, clazz: KClass<*>) {
    val fields = extractColumns(clazz)
    val primaryKeys = fields
            .filter { it.primaryKey }
            .map { it.name }

    val createQuery = "CREATE TABLE IF NOT EXISTS `${clazz.simpleName}` (" +
            fields.joinToString(", ") { "`${it.name}` ${it.type} ${it.nonNull}" } +
            ", PRIMARY KEY (" + primaryKeys.joinToString(",") { "`$it`" } +
            "))"
    db.execSQL(createQuery)
}

fun extractColumns(clazz: KClass<*>): Array<Column>{
    val columns = ArrayList<Column>()
    for (field in clazz.declaredMemberProperties){
        val name = field.findAnnotation<ColumnInfo>()?.name ?: field.name
        val type = getSqlType(field.returnType)
        val nonNull = if (field.returnType.isMarkedNullable) "" else "NON NULL"
        val primaryKey = field.findAnnotation<PrimaryKey>() != null
        columns.add(Column(name, type, nonNull, primaryKey))
    }
    return columns.toTypedArray()
}

Но проблема в том, что Аннотации комнат помечены @Retention(RetentionPolicy.CLASS), к которым можно получить доступ только во время компиляции.Они не доступны во время выполнения.Так что все мои findAnnotation методы вернут null.Я думал о создании во время компиляции, но не мог придумать, как это сделать.

Итак, мой вопрос был: есть ли способ генерировать скрипты CREATE во время компиляции и если да, то как это сделать?

Помимо упомянутого мной способа решения, есть ли другой способ создания таблиц, который не включает в себя первые два метода вставки копий?

И, кстати, я не рассматриваю fallbackToDestructiveMigration,Я имею в виду, кто бы хотел, чтобы их пользователи потеряли все данные?

1 Ответ

0 голосов
/ 19 июля 2019

Начиная с текущего обновления Room, фактически существует способ создания SQL запросов с использованием Annotation Processing.При обработке аннотаций вам нужно написать небольшую библиотеку, которая генерирует для вас Room запросов при ее создании.

Создание Annotation Processing Library не так просто, и здесь возникает связанная с этим проблема.

Перенос базы данных комнаты, если добавлена ​​только новая таблица

...