Je migre de SQlite vers room dans mon application existante. Par conséquent, j'ai créé une stratégie de migration pour créer de nouvelles tables temporaires, copier les données existantes dans des tables temporaires, supprimer les anciennes tables et renommer les nouvelles tables.

Après la migration, j'ai vérifié mon schéma exporté et il est exactement le même que le schéma attendu, mais j'obtiens toujours l'erreur de mon ancien schéma trouvée et l'erreur de réception ci-dessous. Les principales différences sur les erreurs de schéma sont "type" et #notNull" mais je les ai déjà corrigées lors de la migration

La base de données préemballée a un schéma non valide : User(com.afl.waterReminderDrinkAlarmMonitor.model.User)

Mon entité utilisateur

@Entity(tableName = "User" )
data class User(
    @PrimaryKey
    var id: Int = 0,
    var age: Int = 0,
    var weight: Int = 0,
    var gender: String = "",
    var metric: String = "",
    var water: Int = 0
)

AppDatabase

abstract class AppDatabase : RoomDatabase() {

    abstract fun dao(): Dao

    companion object {

        @Volatile
        private var INSTANCE: AppDatabase? = null

    val migration_1_2 = object : Migration(1, 2) {
        override fun migrate(database: SupportSQLiteDatabase) {

            //COPY USER TABLE
            // Create new  table
            database.execSQL("CREATE TABLE IF NOT EXISTS UserTmp ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_WEIGHT INTEGER NOT NULL, $COL_GENDER  TEXT NOT NULL,$COL_METRIC TEXT NOT NULL, $COL_AGE INTEGER NOT NULL, $COL_WATER INTEGER NOT NULL)")
            // Copy the data
            database.execSQL("INSERT INTO UserTmp ($COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER) SELECT $COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER FROM $TABLE_NAME ")
            // Remove the old table
            database.execSQL("DROP TABLE $TABLE_NAME")
            // Change the table name to the correct one
            database.execSQL("ALTER TABLE UserTmp RENAME TO $TABLE_NAME")

            //COPY DRUNK TABLE
            // Create new table
            database.execSQL("CREATE TABLE IF NOT EXISTS DrunkTmp ($COL_ID_DRUNK INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_DATE_DRUNK TEXT NOT NULL, $COL_TIME_DRUNK TEXT NOT NULL,$COL_DRINK_DRUNK TEXT NOT NULL, $COL_AMOUNT_DRUNK INTEGER NOT NULL ,$COL_METRIC_DRUNK TEXT NOT NULL)")
            // Copy the data
            database.execSQL("INSERT INTO DrunkTmp ($COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK) SELECT $COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK FROM $TABLE_NAME_DRUNK")
            // Remove the old table
            database.execSQL("DROP TABLE $TABLE_NAME_DRUNK")
            // Change the table name to the correct one
            database.execSQL("ALTER TABLE DrunkTmp RENAME TO $TABLE_NAME_DRUNK")

            //COPY NOT TABLE
            // Create new table
            database.execSQL("CREATE TABLE IF NOT EXISTS NotificationTmp ($COL_ID_NOT INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_PREF_NOT INTEGER NOT NULL, $COL_START_NOT INTEGER NOT NULL, $COL_FINISH_NOT INTEGER NOT NULL,$COL_INTERVAL_NOT INTEGER NOT NULL)")
            // Copy the data
            database.execSQL("INSERT INTO NotificationTmp ($COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT) SELECT $COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT FROM $TABLE_NAME_NOT ")
            // Remove the old table
            database.execSQL("DROP TABLE $TABLE_NAME_NOT")
            // Change the table name to the correct one
            database.execSQL("ALTER TABLE NotificationTmp RENAME TO $TABLE_NAME_NOT")
        }

    }

        fun getDatabase(context: Context?): AppDatabase {

            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }

            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context?.applicationContext!!,
                    AppDatabase::class.java, DATABASE_NAME
                )
                    .addMigrations(migration_1_2)
                    .build()
                INSTANCE = instance
                return instance
            }
        }

    }


}

Schéma exporté pour l'utilisateur

  {
    "tableName": "User",
    "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `age` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `gender` TEXT NOT NULL, `metric` TEXT NOT NULL, `water` INTEGER NOT NULL, PRIMARY KEY(`id`))",
    "fields": [
      {
        "fieldPath": "id",
        "columnName": "id",
        "affinity": "INTEGER",
        "notNull": true
      },
      {
        "fieldPath": "age",
        "columnName": "age",
        "affinity": "INTEGER",
        "notNull": true
      },
      {
        "fieldPath": "weight",
        "columnName": "weight",
        "affinity": "INTEGER",
        "notNull": true
      },
      {
        "fieldPath": "gender",
        "columnName": "gender",
        "affinity": "TEXT",
        "notNull": true
      },
      {
        "fieldPath": "metric",
        "columnName": "metric",
        "affinity": "TEXT",
        "notNull": true
      },
      {
        "fieldPath": "water",
        "columnName": "water",
        "affinity": "INTEGER",
        "notNull": true
      }
    ],
    "primaryKey": {
      "columnNames": [
        "id"
      ],
      "autoGenerate": false
    },
    "indices": [],
    "foreignKeys": []
  }

Et enfin l'erreur je la reçois

java.lang.IllegalStateException: Pre-packaged database has an invalid schema: User(com.afl.waterReminderDrinkAlarmMonitor.model.User).

Expected: TableInfo{name='User', columns={weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, gender=Column{name='gender', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}

Found: TableInfo{name='User', columns={gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
0
sinan 19 févr. 2020 à 01:31

1 réponse

Meilleure réponse

La question manque la base de données pré-remplie, qui réside dans assets ou ailleurs ; car la non-concordance se trouve en fait dans ce fichier et une migration devrait le charger, puis modifier la colonne. Comme on peut le voir, la table User a le mauvais type de données pour les colonnes gender et metric :

Expected: TableInfo{name='User', columns={
       id=Column{name='id',         type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'},
       age=Column{name='age',       type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null',
       weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'},
       gender=Column{name='gender',    type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
       metric=Column{name='metric',    type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
       water=Column{name='water',   type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}

Found:   TableInfo{name='User', columns={
       id=Column{name='id',              type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'},
       age=Column{name='age',            type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue ='null',
       weight=Column{name='weight',      type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'},
       gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
       metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
       water=Column{name='water',        type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}

La modification de la base de données packagée sur un ordinateur peut être le moindre effort.

1
Martin Zeitler 19 févr. 2020 à 17:41