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

350

Я использую компонентную базу данных Android

Я все настроил, но при компиляции Android Studio выдает мне следующее предупреждение:

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

Как я понимаю, это место, где будет расположен файл БД

Как это может повлиять на мое приложение? Какова лучшая практика здесь? Должен ли я использовать местоположение по умолчанию ( falseзначение)?

Миша Акопов
источник

Ответы:

396

Согласно документам :

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

Так что, если вам не нужно проверять схему и вы хотите избавиться от предупреждения, просто добавьте exportSchema = falseк своему RoomDatabase, как показано ниже.

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
   //...
}

Если вы будете следовать ответу @mikejonesguy ниже, вы будете следовать рекомендациям, упомянутым в документации :). В основном вы получите .jsonфайл в вашей ../app/schemas/папке. И это выглядит примерно так:

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "53db508c5248423325bd5393a1c88c03",
    "entities": [
      {
        "tableName": "sms_table",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT, `date` INTEGER, `client_id` INTEGER)",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "message",
            "columnName": "message",
            "affinity": "TEXT"
          },
          {
            "fieldPath": "date",
            "columnName": "date",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "clientId",
            "columnName": "client_id",
            "affinity": "INTEGER"
          }
        ],
        "primaryKey": {
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"53db508c5248423325bd5393a1c88c03\")"
    ]
  }
}

Если мое понимание верно, вы будете получать такой файл при каждом обновлении версии базы данных, чтобы вы могли легко следить за историей вашей базы данных.

DoruChidean
источник
8
Что на самом деле означает «Не отправляйте вместе с вашим приложением»? Это будет включено в APK?
Йонгз Пуангпут
2
Если следовать пункту «Не отправлять вместе с вашим приложением», следует ли удалять файлы JSON перед созданием APK?
illusionJJ
8
«Не поставлять вместе с вашим приложением» означает «Не устанавливайте schemaLocation как« app / res / raw ». Установите schemaLocation в каталог, не включенный в APK».
Galcyurio
3
@galcyurio $ projectDir / schemas - это каталог вне APK, верно? Я исследовал созданный APK и не вижу его там. Хотя я вижу / res (который отвечает за app / src / main / res) например.
xarlymg89
1
@glucaio Я изучил APK (и пакет приложений тоже) и не нашел его. Поэтому я верю, что мы в безопасности.
xarlymg89
390

В build.gradleфайле для модуля приложения добавьте его в defaultConfigраздел (под androidразделом). Это запишет схему в schemasподпапку папки вашего проекта.

javaCompileOptions {
    annotationProcessorOptions {
        arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
    }
}

Как это:

// ...

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // ... (buildTypes, compileOptions, etc)

}

// ...
mikejonesguy
источник
36
Если кому-то интересно, этот точный подход также работает для Kotlin при использовании kapt
DanielDiSu
1
Должны ли мы gitignore файл json, сгенерированный в app/schemasкаталоге этой операцией. И я слышал, что мы должны поместить схему в каталог, который не включен в apk. Как мы можем сделать это?
Рави
2
@ravi сгенерированные файлы схемы должны быть сохранены в системе контроля версий, так как это используется Room для обнаружения изменений и помогает гарантировать, что при изменении базы данных вы обновите версию базы данных и создадите план миграции
appmattus
1
Эта конфигурация влияет на версию выпуска? Я имею в виду, когда я экспортирую проект в релизное приложение.
Анаргу
Если это решение приводит к ОШИБКЕ: Не удалось найти метод annotationProcessorOptions () для аргументов , посмотрите ответ Луны, приведенный ниже: stackoverflow.com/a/54366985/1617737
ban-
185

Котлин? Вот так:

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
    }

    buildTypes {
        // ... (buildTypes, compileOptions, etc)
    }
}

//...

Не забудьте про плагин:

apply plugin: 'kotlin-kapt'

Для получения дополнительной информации о процессоре аннотаций kotlin, пожалуйста, посетите: Kotlin docs

Иванов Максим
источник
Как и вы ответили: D
theapache64
12

Выше ответы верны. Эту версию легко понять:

Поскольку «Каталог экспорта схемы не предоставляется процессору аннотаций», поэтому нам необходимо предоставить каталог для экспорта схемы:

Шаг [1] В вашем файле, который расширяет RoomDatabase, измените строку на:

`@Database(entities = ???.class,version = 1, exportSchema = true)`

Или

`@Database(entities = ???.class,version = 1)` 

(потому что значение по умолчанию всегда верно)

Шаг [2] В вашем файле build.gradle (project: ????), внутри defaultConfig {} (который находится внутри большого раздела android {} ), добавьте раздел javaCompileOptions {} , это будет выглядеть так:

         android{
                defaultConfig{
                      //javaComplieOptions SECTION
                      javaCompileOptions {
                            annotationProcessorOptions {
                                     arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
                            }
                       }
                      //Other SECTION
                      ...
                }
         }

$ projectDir : это имя переменной, вы не можете его изменить. он получит ваш собственный каталог проектов

схемы : это строка, вы можете изменить ее на любую, какую захотите. Например: "$projectDir/MyOwnSchemas".toString()

LunaRivolxoxo
источник
на шаге [2] вы уверены, что это build.gradle(project:????)и нет build.gradle(app:????)?
Ace
9

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

В вашем файле build.gradle вы указываете папку для размещения этих сгенерированных файлов JSON схемы. При обновлении схемы вы получите несколько файлов JSON, по одному для каждой версии. Убедитесь, что вы передаете каждый сгенерированный файл в систему контроля версий. В следующий раз, когда вы снова увеличите номер версии, Room сможет использовать файл JSON для тестирования.

build.gradle

android {

    // [...]

    defaultConfig {

        // [...]

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // add the schema location to the source sets
    // used by Room, to test migrations
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }

    // [...]
}
chebaby
источник
3

Я использую .ktsфайлы Gradle (Kotlin Gradle DSL) и kotlin-kaptплагин, но все равно получаю ошибку компиляции скрипта, когда использую ответ Иванова Максима.

Unresolved reference: kapt

Для меня это было единственное, что сработало:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf("room.schemaLocation" to "$projectDir/schemas")
            }
        }
    }
}
АПБ
источник
У меня тоже ничего не работает. Я использую Kotlin.
nyxee
0

Возможно, вы не добавили свой класс комнаты в RoomDatabaseдетский класс в@Database(entities = {your_classes})

Макс Зонов
источник