房间迁移未找到 Table 列
Room Migration Not Finding Table Columns
我想从我的 sqlite 数据库中的 table 中删除一些列。我创建了一个新的 table(名称不同),将旧 table 中的适当数据插入到新 table 中。然后我删除了旧的 table 并将新的 table 重命名为旧的 table 的名称。
但是我收到这个错误
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=[]}
我的衣服 class 已更改以反映我删除的列,但我不确定为什么找不到这些列
衣服class
@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;
}
}
}
我从你的代码中看到了什么:
- 设备上的当前数据库版本(迁移前)似乎是 12。
- 据此:
@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 14)
您正在尝试将数据库版本更改为 14。
- 从 12 版本更新到 14 版本将调用两种迁移方法:MIGRATION_12_13 和 MIGRATION_13_14。 Sqlite中的这些方法后会有ClothingItems table, table Clothes会掉落。您在 post 中写道
renamed the new table to the old table's name
但我看不到你的 SQL 声明(没有 "ALTER TABLE" 声明)。
- 因此,在迁移后,Sqlite 只知道 ClothingItems table,但您仍然在实体注释中使用 table 的名称 "Clothes":
@Entity(tableName = "Clothes")
public class ClothingItem implements Parcelable {
我猜这会导致错误消息(预期一些 table 但不存在)。
命题:
- 添加到您的迁移 SQL-语句以将您的新 table 重命名为旧 table 的名称 ("ALTER TABLE ... RENAME TO ...")
或
- 在您的实体中使用新的 table 名称 - "ClothingItems"
经过大量研究后,我从 Lua Software Code 中找到了答案,我意识到我没有在我的数据库中使用 exportSchema class。
@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 15,exportSchema = true)
它会在每次添加迁移时在资产文件夹下创建一个 JSON,这样您就可以看到 SQL 命令发生了什么
一旦我添加了它并在没有 运行 的情况下构建了项目,我就可以看到 table 是如何创建的。
事实证明,我的其中一个专栏已更改为 "Not Null",这就是导致错误的原因。
我想从我的 sqlite 数据库中的 table 中删除一些列。我创建了一个新的 table(名称不同),将旧 table 中的适当数据插入到新 table 中。然后我删除了旧的 table 并将新的 table 重命名为旧的 table 的名称。 但是我收到这个错误
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=[]}
我的衣服 class 已更改以反映我删除的列,但我不确定为什么找不到这些列
衣服class
@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;
}
}
}
我从你的代码中看到了什么:
- 设备上的当前数据库版本(迁移前)似乎是 12。
- 据此:
@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 14)
您正在尝试将数据库版本更改为 14。
- 从 12 版本更新到 14 版本将调用两种迁移方法:MIGRATION_12_13 和 MIGRATION_13_14。 Sqlite中的这些方法后会有ClothingItems table, table Clothes会掉落。您在 post 中写道
renamed the new table to the old table's name
但我看不到你的 SQL 声明(没有 "ALTER TABLE" 声明)。
- 因此,在迁移后,Sqlite 只知道 ClothingItems table,但您仍然在实体注释中使用 table 的名称 "Clothes":
@Entity(tableName = "Clothes")
public class ClothingItem implements Parcelable {
我猜这会导致错误消息(预期一些 table 但不存在)。
命题:
- 添加到您的迁移 SQL-语句以将您的新 table 重命名为旧 table 的名称 ("ALTER TABLE ... RENAME TO ...")
或
- 在您的实体中使用新的 table 名称 - "ClothingItems"
经过大量研究后,我从 Lua Software Code 中找到了答案,我意识到我没有在我的数据库中使用 exportSchema class。
@Database(entities = {ClothingItem.class, DailyOutfit.class}, version = 15,exportSchema = true)
它会在每次添加迁移时在资产文件夹下创建一个 JSON,这样您就可以看到 SQL 命令发生了什么 一旦我添加了它并在没有 运行 的情况下构建了项目,我就可以看到 table 是如何创建的。 事实证明,我的其中一个专栏已更改为 "Not Null",这就是导致错误的原因。