Pokój - katalog eksportu schematu nie jest dostarczany do procesora adnotacji, więc nie możemy eksportować schematu

350

Korzystam z pokoju z komponentami bazy danych Androida

Skonfigurowałem wszystko, ale podczas kompilacji Android Studio wyświetla mi to ostrzeżenie:

Katalog eksportu schematu nie jest dostarczany do procesora adnotacji, więc nie możemy eksportować schematu. Możesz podać room.schemaLocationargument procesora adnotacji LUB ustawić wartość exportSchema na false.

Rozumiem, że jest to lokalizacja, w której będzie znajdować się plik DB

Jak może to wpłynąć na moją aplikację? Jaka jest tutaj najlepsza praktyka? Czy powinienem użyć domyślnej lokalizacji ( falsewartości)?

Misza Akopow
źródło

Odpowiedzi:

396

Zgodnie z dokumentami :

Możesz ustawić argument procesora adnotacji (room.schemaLocation), aby poinformować Room o wyeksportowaniu schematu do folderu. Chociaż nie jest to obowiązkowe, dobrą praktyką jest posiadanie historii wersji w bazie kodu i powinieneś zatwierdzić ten plik w systemie kontroli wersji (ale nie dostarczaj go wraz z aplikacją!).

Więc jeśli nie musisz sprawdzać schematu i chcesz pozbyć się ostrzeżenia, po prostu dodaj exportSchema = falsedo niego RoomDatabasew następujący sposób.

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

Jeśli zastosujesz się do odpowiedzi @mikejonesguy poniżej, będziesz postępować zgodnie z dobrą praktyką wymienioną w dokumentacji :). Zasadniczo otrzymasz .jsonplik w swoim ../app/schemas/folderze. I wygląda to tak:

{
  "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\")"
    ]
  }
}

Jeśli moje zrozumienie jest poprawne, otrzymasz taki plik przy każdej aktualizacji wersji bazy danych, abyś mógł łatwo śledzić historię swojego db.

DoruChidean
źródło
8
Co to tak naprawdę znaczy „Nie wysyłaj z aplikacją”? Będzie zawarty w APK?
Jongz Puangput,
2
Jeśli postępujesz zgodnie z instrukcjami „Nie dostarczaj z aplikacją”, czy powinienem usunąć pliki JSON przed wygenerowaniem APK?
illusionJJ
8
„Nie wysyłaj z aplikacją” oznacza „Nie ustawiaj schemaLocation na„ app / res / raw ”. Ustaw schemaLocation na katalog nieuwzględniony w APK”.
galcyurio
3
@galcyurio $ projectDir / schemas to katalog poza pakietem APK, prawda? Sprawdziłem wygenerowany pakiet APK i nie widzę go tam. Chociaż na przykład widzę / res (która odpowiada za app / src / main / res).
xarlymg89,
1
@glucaio Odkryłem APK (i pakiet aplikacji) i nie znalazłem go. Więc wierzę, że jesteśmy bezpieczni.
xarlymg89,
390

W build.gradlepliku modułu aplikacji dodaj to do defaultConfigsekcji (pod androidsekcją). Spowoduje to zapisanie schematu do schemaspodfolderu folderu projektu.

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

Lubię to:

// ...

android {

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

    defaultConfig {

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

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

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

}

// ...
mikejonesguy
źródło
35
Jeśli ktoś się zastanawia, to dokładne podejście działa również w przypadku Kotlin podczas używania kaptura
DanielDiSu,
1
Czy powinniśmy pobrać plik json wygenerowany w app/schemaskatalogu przez tę operację? I słyszałem, że powinniśmy umieścić schemat w katalogu, który nie jest zawarty w katalogu apk. Jak możemy to zrobić?
ravi
2
@ravi wygenerowane pliki schematu powinny być przechowywane w kontroli wersji, ponieważ jest on wykorzystywany przez Room do wykrywania zmian i pomaga upewnić się, że w przypadku zmian w bazie danych zaktualizujesz wersję bazy danych i utworzysz plan migracji
appmattus
1
Czy ta konfiguracja wpływa na wersję? Mam na myśli, gdy eksportuję projekt do aplikacji w wersji.
Anargu,
Jeśli to rozwiązanie spowoduje BŁĄD: nie można znaleźć metody adnotacjiProcessorOptions () dla argumentów , sprawdź odpowiedź Luny poniżej: stackoverflow.com/a/54366985/1617737
ban-geoengineering
185

Kotlin? No to ruszamy:

android {

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

    defaultConfig {

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

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

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

//...

Nie zapomnij o wtyczce:

apply plugin: 'kotlin-kapt'

Aby uzyskać więcej informacji na temat procesora adnotacji Kotlin, odwiedź: Dokumenty Kotlin

Iwanow Maksim
źródło
Tak jak odpowiedziałeś: D
theapache64
12

Powyższe odpowiedzi są poprawne. Ta wersja jest łatwa do naśladowania:

Ponieważ „Katalog eksportu schematu nie jest dostarczany do procesora adnotacji”, musimy udostępnić katalog do eksportu schematu:

Krok [1] W pliku rozszerzającym RoomDatabase zmień wiersz na:

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

Lub

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

(ponieważ wartość domyślna jest zawsze prawdziwa)

Krok [2] W swojej build.gradle (projekt: ????) plików wewnątrz defaultConfig {} (co jest wewnątrz android {} duże części), dodać javaCompileOptions {} sekcję, to będzie tak:

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

$ projectDir : to nazwa zmiennej, której nie można zmienić. otrzyma własny katalog projektów

schematy : to ciąg znaków, który możesz zmienić na dowolny. Na przykład: "$projectDir/MyOwnSchemas".toString()

LunaRivolxoxo
źródło
w kroku [2], czy jesteś pewien, że to build.gradle(project:????)i nie build.gradle(app:????)?
Ace
9

Odpowiedź @mikejonesguy jest idealna, na wypadek, gdybyś planował przetestować migracje pokoju (zalecane), dodaj lokalizację schematu do zestawów źródłowych.

W pliku build.gradle określasz folder, w którym zostaną umieszczone wygenerowane pliki JSON schematu. Po zaktualizowaniu schematu powstanie kilka plików JSON, po jednym dla każdej wersji. Upewnij się, że przekazujesz każdy wygenerowany plik do kontroli źródła. Następnym razem, gdy ponownie zwiększysz numer wersji, Room będzie mógł użyć pliku JSON do testowania.

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
źródło
3

Używam .ktsplików Gradle (Kotlin Gradle DSL) i kotlin-kaptwtyczki, ale nadal pojawia się błąd kompilacji skryptu, gdy używam odpowiedzi Iwanowa Maksima.

Unresolved reference: kapt

Dla mnie była to jedyna rzecz, która działała:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf("room.schemaLocation" to "$projectDir/schemas")
            }
        }
    }
}
jsa
źródło
Dla mnie też nic nie działa. Używam Kotlina.
nyxee
0

Prawdopodobnie nie dodać klasę pokoju, aby dziecko RoomDatabaseklasie dzieci w@Database(entities = {your_classes})

Max Zonov
źródło