房间迁移未找到表列

时间:2020-05-16 20:55:10

标签: android sqlite android-studio android-room database-migration

我想从我的sqlite数据库中的表中删除一些列。我创建了一个新表(使用不同的名称),并将适当的数据从旧表插入到新表中。然后,我删除了旧表,并将新表重命名为旧表的名称。 但是我收到此错误

 Caused by: java.lang.IllegalStateException: Migration didn't properly handle: Clothes(com.dayaramo.wearyourcloset.Objects.ClothingItem).
     Expected:
    TableInfo{name='Clothes', columns={season=Column{name='season', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, item=Column{name='item', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, wornCount=Column{name='wornCount', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, category=Column{name='category', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, photoPath=Column{name='photoPath', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
     Found:
    TableInfo{name='Clothes', columns={}, foreignKeys=[], indices=[]}

我的Clothing类更改为反映了我删除的列,但是我不确定为什么找不到这些列

服装课

@Entity(tableName = "Clothes")
public class ClothingItem implements Parcelable {

    @PrimaryKey(autoGenerate = true)
    private long id;
    private String item;
    private String season;
    private String category;
    private int wornCount;
    private String photoPath;



    public static final Creator<ClothingItem> CREATOR = new Creator<ClothingItem>() {
        @Override
        public ClothingItem createFromParcel(Parcel in) {
            return new ClothingItem(in);
        }

        @Override
        public ClothingItem[] newArray(int size) {
            return new ClothingItem[size];
        }
    };

    public void setId(long id) {
        this.id = id;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public void setSeason(String season) {
        this.season = season;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public void setPhotoPath(String photoPath) {
        this.photoPath = photoPath;
    }


    public void setWornCount(int wornCount) { this.wornCount = wornCount; }

    @Ignore
    public ClothingItem(String item, String season, String category, int wornCount) {
        this.item = item;
        this.season = season;
        this.category = category;
        this.wornCount = wornCount;
    }

    public ClothingItem(String item, String season, String category, int wornCount, String photoPath) {
        this.item = item;
        this.season = season;
        this.category = category;
        this.wornCount = wornCount;
        this.photoPath = photoPath;
    }

    @Ignore
    public ClothingItem() {
    }

    public String getItem() {
        return item;
    }

    public String getCategory() {
        return category;
    }

    public String getSeason() {
        return season;
    }

    public String getPhotoPath() {
        return photoPath;
    }


    public long getId() {return id; }

    public int getWornCount() { return wornCount; }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(id);
        dest.writeString(item);
        dest.writeString(season);
        dest.writeString(category);
        dest.writeInt(wornCount);
        dest.writeString(photoPath);
    }

    protected ClothingItem(Parcel in) {
        id = in.readLong();
        item = in.readString();
        season = in.readString();
        category = in.readString();
        wornCount = in.readInt();
        photoPath = in.readString();
    }
}

迁移代码

@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 14)
public abstract class ClothingItemDatabase extends RoomDatabase {

    public abstract ClothingDao clothingDao();
//    public abstract OutfitDao outfitDao();
    public abstract DailyOutfitDao dailyOutfitDao();

    private static volatile ClothingItemDatabase INSTANCE;
    private static final Object sLock = new Object();

....
 static final Migration MIGRATION_12_13 = new Migration(12,13) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {

            database.execSQL("CREATE TABLE `ClothingItems` (`id` INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "`item` TEXT, `season` TEXT, `category` TEXT, `wornCount` INTEGER, `photoPath` TEXT)");

            database.execSQL("INSERT INTO `ClothingItems` (`id`,`item`, `season`,`category`,`wornCount`,`photoPath`)" +
                    "SELECT `id`,`item`, `season`,`category`,`wornCount`,`photoPath` from Clothes");

        }
    };

    static final Migration MIGRATION_13_14 = new Migration(13,14) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {

            database.execSQL("DELETE FROM `Clothes`");
            database.execSQL("DROP TABLE `Clothes`");
        }
    };


    static final Migration MIGRATION_14_15 = new Migration(14, 15) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {

            database.execSQL("DELETE FROM `DailyOutfits`");

        }
    };

 static final Migration MIGRATION_15_16 = new Migration(15, 16) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {

//            database.execSQL("DROP TABLE `Outfits`");
        }
    };



    static  ClothingItemDatabase getDatabase(final Context context) {

        if (INSTANCE == null) {

            synchronized (ClothingItemDatabase.class) {
                if (INSTANCE == null) {

                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            ClothingItemDatabase.class, "Clothes")
                            .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4,MIGRATION_4_5,MIGRATION_5_6,MIGRATION_6_7
                                    ,MIGRATION_8_9,MIGRATION_9_10, MIGRATION_10_11,MIGRATION_11_12,MIGRATION_12_13,MIGRATION_13_14,MIGRATION_14_15,MIGRATION_15_16)
                            .addCallback(sRoomDatabaseCallback).build();
                }
            }
        }

        return INSTANCE;
    }
//    MIGRATION_7_8, MIGRATION_8_9, MIGRATION_9_10)

    private static Callback sRoomDatabaseCallback = new Callback() {

        @Override
        public void onOpen(@NonNull SupportSQLiteDatabase db) {
            super.onOpen(db);
        }
    };


    /*
     * Migrate from:
     * version 1 - using the SQLiteDatabase API
     * to
     * version 2 - using Room
     * November 12,2019
     * Migrate from:
     * version 3 - using the SQLiteDatabase API
     * to
     * version 4 - using Room
     * March 19, 2020
     *to
     * version 5
     * May 3, 2020
     *to
     *version 5,6,7
     * May 3, 2020
     */


    public static ClothingItemDatabase getInstance(Context context) {
        synchronized (sLock) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                        ClothingItemDatabase.class, "ClothingItem.db")
                        .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4,MIGRATION_4_5,MIGRATION_5_6,
                                MIGRATION_6_7,MIGRATION_8_9,MIGRATION_9_10,MIGRATION_10_11, MIGRATION_11_12,MIGRATION_12_13,MIGRATION_13_14,MIGRATION_14_15,MIGRATION_15_16)
                        .fallbackToDestructiveMigration()
                        .build();
            }
            return INSTANCE;
        }
    }
}


2 个答案:

答案 0 :(得分:1)

经过大量研究,我从Lua Software Code找到了答案,在那里我意识到我没有在数据库类中使用exportSchema。

@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 15,exportSchema = true)

每次添加迁移时,它都会在assets文件夹下创建一个JSON,因此您可以查看SQL命令的情况 添加完并构建了没有运行它的项目后,我可以看到如何创建表。 原来,我的一列已更改为“ Not Null”,这就是导致该错误的原因。

答案 1 :(得分:0)

我从您的代码中看到的内容

  1. 看来(迁移之前)设备上数据库的当前版本为12。
  2. 据此:
@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 14)

您正在尝试将数据库版本更改为14。

  1. 将版本从12更新到14将调用两种迁移方法:MIGRATION_12_13和MIGRATION_13_14。在Sqlite中使用这些方法之后,将出现ClothingItems表,并将删除Table Clothes。您在帖子中写了

将新表重命名为旧表的名称

但是我看不到您的SQL语句(没有“ ALTER TABLE”语句)。

  1. 因此,迁移后Sqlite仅了解ClothingItems表,但您仍在Entity批注中使用表的名称“ Clothes”:
@Entity(tableName = "Clothes")
public class ClothingItem implements Parcelable {

我猜这会导致错误消息(预计会有一些表,但不存在)。

主张

  1. 要添加到迁移SQL语句中,以将新表重命名为旧表的名称(“ ALTER TABLE ... RENAME TO ...”)

  1. 要在您的实体中使用新表的名称-“ ClothingItems”