Android 如何在Room的数据库迁移中正确添加索引?

Android 如何在Room的数据库迁移中正确添加索引?,android,Android,我在迁移我的房间数据库时遇到问题。在更新的数据库中,我必须将一个字段从整数改为双倍值。我读到它并不像听起来那么容易,为了做到这一点,我必须用这个已更改的属性创建新的临时表,复制以前表中的所有值,删除旧表,最后重命名临时表 我的实体有2个索引,这导致了问题。这是我目前最好的解决方案,它没有通过自动生成的房间迁移验证 oceny是原始表的名称,oceny_temp是临时名称。即使我使用create index显式地将这些索引添加到中,但验证仍然没有通过,因为它表明in expected table有

我在迁移我的房间数据库时遇到问题。在更新的数据库中,我必须将一个字段从整数改为双倍值。我读到它并不像听起来那么容易,为了做到这一点,我必须用这个已更改的属性创建新的临时表,复制以前表中的所有值,删除旧表,最后重命名临时表

我的实体有2个索引,这导致了问题。这是我目前最好的解决方案,它没有通过自动生成的房间迁移验证

oceny是原始表的名称,oceny_temp是临时名称。即使我使用create index显式地将这些索引添加到中,但验证仍然没有通过,因为它表明in expected table有2个索引,in found有0个索引

static final Migration MIGRATION_25_26 = new Migration(25,26) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {

        database.execSQL("CREATE TABLE IF NOT EXISTS oceny_temp" +
                        "(`idOceny` TEXT NOT NULL, " +
                        "`idUcznia` TEXT, " +
                        "`idPrzedmiotu` TEXT, " +
                        "`semestr` INTEGER NOT NULL, " +
                        "`typOceny` INTEGER NOT NULL, " +
                        "`wartosc` TEXT, " +
                        "`wartoscDoSredniej` REAL, " +
                        "`czyProponowana` INTEGER NOT NULL, " +
                        "`kategoria` TEXT, " +
                        "`waga` REAL NOT NULL, " +
                        "`maxPunktow` REAL NOT NULL, " +
                        "`odczytana` INTEGER NOT NULL, " +
                        "`dataWystawienia` TEXT, " +
                        "`wystawiajacy` TEXT, " +
                        "`typOczekiwania` INTEGER NOT NULL, " +
                        "`wersjaRekordu` TEXT, " +
                        "`rekordUsuniety` INTEGER NOT NULL, " +
                        "PRIMARY KEY(`idOceny`), " +
                        "FOREIGN KEY(`idUcznia`) REFERENCES `uczniowie`(`idUcznia`) ON UPDATE NO ACTION ON DELETE CASCADE )");

        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny_temp (idPrzedmiotu)");
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny_temp (idUcznia)");


        // Copy the data
        database.execSQL(
                "INSERT INTO oceny_temp (idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety) " +
                                "SELECT idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety FROM oceny");

        // Remove the old table
        database.execSQL("DROP TABLE oceny");

        // Change the table name to the correct one
        database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");
    }
};
错误消息:

Migration didn't properly handle 

oceny(de.wolterskluwer.idziennik.model.grades.Grade).
 Expected:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[Index{name='index_oceny_idPrzedmiotu', unique=false, columns=[idPrzedmiotu]}, Index{name='index_oceny_idUcznia', unique=false, columns=[idUcznia]}]}
 Found:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[]}

附加信息:我将IF NOT EXISTS添加到create索引中,因为它说该索引已经存在,这对我来说没有意义。重命名表时,索引似乎丢失了。因此,在将时态表重命名为正确的时态表之后,我又添加了一行,从而解决了这个问题。这将在重命名的表上创建索引。你的情况是这样的

    // Change the table name to the correct one
    database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");

    // Create the indices on the table
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny (idPrzedmiotu)");
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny (idUcznia)");

    

问题是您正在发送一个“createindex IF NOT EXISTS”命令,但是同名的索引已经存在,因此不会创建新索引

您可以通过在尝试创建新索引之前删除现有索引,或者简单地在流的末尾移动CREATEINDEX命令来解决此问题

下面是应该可以工作的完整代码:

static final Migration MIGRATION_25_26 = new Migration(25,26) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {

        database.execSQL("CREATE TABLE IF NOT EXISTS oceny_temp" +
                        "(`idOceny` TEXT NOT NULL, " +
                        "`idUcznia` TEXT, " +
                        "`idPrzedmiotu` TEXT, " +
                        "`semestr` INTEGER NOT NULL, " +
                        "`typOceny` INTEGER NOT NULL, " +
                        "`wartosc` TEXT, " +
                        "`wartoscDoSredniej` REAL, " +
                        "`czyProponowana` INTEGER NOT NULL, " +
                        "`kategoria` TEXT, " +
                        "`waga` REAL NOT NULL, " +
                        "`maxPunktow` REAL NOT NULL, " +
                        "`odczytana` INTEGER NOT NULL, " +
                        "`dataWystawienia` TEXT, " +
                        "`wystawiajacy` TEXT, " +
                        "`typOczekiwania` INTEGER NOT NULL, " +
                        "`wersjaRekordu` TEXT, " +
                        "`rekordUsuniety` INTEGER NOT NULL, " +
                        "PRIMARY KEY(`idOceny`), " +
                        "FOREIGN KEY(`idUcznia`) REFERENCES `uczniowie`(`idUcznia`) ON UPDATE NO ACTION ON DELETE CASCADE )");


        // Copy the data
        database.execSQL(
                "INSERT INTO oceny_temp (idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety) " +
                                "SELECT idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety FROM oceny");

        // Remove the old table
        database.execSQL("DROP TABLE oceny");

        // Change the table name to the correct one
        database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");

        // Recreate the indices
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny (idPrzedmiotu)");
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny (idUcznia)");
    }
};

请注意,因为我们已经在流的末尾重命名了表,所以我们在迁移的表上创建了索引。

找到答案了吗。我面临着同样的问题。我也面临着同样的问题。第一个索引应该是database.execSQL(“创建索引,如果不存在的话,索引_oceny_idPrzedmiotu ON oceny(idPrzedmiotu)”;您缺少要添加的_idPrzedmiotu。