【问题标题】:Android Room migration failing due to finding null indices由于找到空索引,Android Room 迁移失败
【发布时间】:2021-04-25 05:37:22
【问题描述】:

我正在尝试进行房间迁移并添加一个带有索引的新表,但它失败了。

实体:

@Entity(tableName = "ring" ,
    foreignKeys = [ForeignKey(entity = BellScheduleRoom::class,
                         parentColumns = arrayOf("code"),
                         childColumns = arrayOf("bellScheduleCode"),
                         onUpdate = ForeignKey.CASCADE,
                         onDelete = ForeignKey.CASCADE)],
    indices = [Index(value = ["bellScheduleCode"])])
data class RingRoom(
        @PrimaryKey
        @ColumnInfo(name = "id", defaultValue = "0")
        var id: Int = 0) {

    @ColumnInfo(name = "dayOfWeek", defaultValue = "0")
    var dayOfWeek: Int = 0
    @ColumnInfo(name = "timeStart", defaultValue = "")
    var timeStart: String = ""
    @ColumnInfo(name = "durationInSeconds", defaultValue = "0")
    var durationInSeconds: Int = 0
    @ColumnInfo(name = "repeats", defaultValue = "0")
    var repeats: Int = 0
    @ColumnInfo(name = "bellScheduleCode", defaultValue = "")
    var bellScheduleCode: String = ""

    override fun toString(): String {
        return "Ring: \n \t id: $id\n \t dayOfWeek: $dayOfWeek\n \t timestart: $timeStart\n \t 
                durationInSeconds: $durationInSeconds\n \t repeats: $repeats"
    }

    constructor(id: Int, dayOfWeek: Int, timeStart: String, durationInSeconds: Int, repeats: Int, 
        bellScheduleCode: String): this(id){
        this.dayOfWeek= dayOfWeek
        this.timeStart = timeStart
        this.durationInSeconds = durationInSeconds
        this.repeats = repeats
        this.bellScheduleCode = bellScheduleCode
    }
}

迁移:

class Migration_1_2 : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("CREATE TABLE `bell_schedule` (`description` TEXT NOT NULL DEFAULT '', `code` TEXT NOT NULL DEFAULT '' , PRIMARY KEY(`code`))")
        database.execSQL("CREATE TABLE `ring` (`dayOfWeek` INTEGER NOT NULL DEFAULT 0, `timeStart` TEXT NOT NULL DEFAULT '', `durationInSeconds` INTEGER NOT NULL DEFAULT 0, `repeats` INTEGER NOT NULL DEFAULT 0, `bellScheduleCode` TEXT NOT NULL DEFAULT '', `id` INTEGER NOT NULL DEFAULT 1, PRIMARY KEY(`id`), FOREIGN KEY(`bellScheduleCode`) REFERENCES `bell_Schedule`(`code`) ON UPDATE CASCADE ON DELETE CASCADE )")

        database.execSQL("CREATE INDEX `index_ring_bellScheduleCode` ON `ring`(`bellScheduleCode`)")
    }
}

运行此迁移测试时,我得到的输出对我来说并不完全有意义。

class TestMigration1to2 {

    private val TEST_DB = "migration-test"

    @Rule @JvmField
    val helper: MigrationTestHelper = MigrationTestHelper(
        InstrumentationRegistry.getInstrumentation(),
        DatabaseRoom::class.java.canonicalName,
        FrameworkSQLiteOpenHelperFactory()
    )

    @Test
    @Throws(IOException::class)
    fun migrate1To2() {
        var db = helper.createDatabase(TEST_DB, 1).apply {
            close()
        }
        db = helper.runMigrationsAndValidate(TEST_DB, 2, true, Migration_1_2())
    }
}

预期(有道理):

TableInfo{name='ring', columns={dayOfWeek=Column{name='dayOfWeek', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, repeats=Column{name='repeats', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='0'}, durationInSeconds=Column{name='durationInSeconds', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, timeStart=Column{name='timeStart', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, bellScheduleCode=Column{name='bellScheduleCode', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}}, foreignKeys=[ForeignKey{referenceTable='bell_schedule', onDelete='CASCADE', onUpdate='CASCADE', columnNames=[bellScheduleCode], referenceColumnNames=[code]}], indices=[]}

找到(这是我的问题):

found: TableInfo{name='ring', columns={dayOfWeek=Column{name='dayOfWeek', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, repeats=Column{name='repeats', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='1'}, durationInSeconds=Column{name='durationInSeconds', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}, timeStart=Column{name='timeStart', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, bellScheduleCode=Column{name='bellScheduleCode', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}}, foreignKeys=[ForeignKey{referenceTable='bell_Schedule', onDelete='CASCADE', onUpdate='CASCADE', columnNames=[bellScheduleCode], referenceColumnNames=[code]}], indices=null}

最让我困惑的部分是indices=null 部分。无论我做什么,找到的索引始终为空。即使我完全删除索引,迁移仍然失败,因为索引为空而不是 []。为什么迁移发现空索引?

【问题讨论】:

    标签: android android-room database-migration


    【解决方案1】:

    我知道这个问题已经有几个月了,昨天我也遇到了同样的问题,原因是我在运行迁移时忘记禁用外键。我正在为外键关系获取此 referenceColumnNames=[null]。

    跑步 PRAGMA foreign_keys=off; 迁移前和 PRAGMA foreign_keys=on; 在它解决了这个问题之后。似乎房间在迁移时默默地未能分配外键,然后在运行时抱怨。

    【讨论】:

      猜你喜欢
      • 2020-04-10
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-31
      • 1970-01-01
      • 2018-06-19
      • 2015-08-12
      相关资源
      最近更新 更多