Java.lang.IllegalStateException
迁移没有得到妥善处理 用户(therealandroid.github.com.roomcore.java.User)。
预期:
TableInfo {name =' user',columns = {name = Column {name =' name',type =' TEXT', notNull = false,primaryKeyPosition = 0},age =列{name =' age', type =' INTEGER',notNull = true,primaryKeyPosition = 0}, id =列{name =' id',type =' INTEGER',notNull = true, primaryKeyPosition = 1}},foreignKeys = []}找到:
实测值
TableInfo {name =' user',columns = {name = Column {name =' name',type =' TEXT', notNull = false,primaryKeyPosition = 0},id =列{name =' id', type =' INTEGER',notNull = true,primaryKeyPosition = 1}, age =列{name =' age',type =' INTEGER',notNull = false, primaryKeyPosition = 0}},foreignKeys = []}
我尝试执行简单迁移,我有一个名为User
的类,它有两列ID (primary key)
和NAME TEXT
,然后我使用两个用户数据填充数据库,然后我在对象AGE
中添加列User
,在迁移常量中添加alter table
以添加此新列,最后我将数据库1的版本替换为2。 / p>
这是代码
User.class
@Entity(tableName = "user")
public class User {
@PrimaryKey
private int id;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "age")
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
数据库类
@Database(entities = {User.class}, version = 2)
public abstract class RoomDatabaseImpl extends RoomDatabase {
abstract UserDao userDao();
}
迁移代码
public static Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE 'user' ADD COLUMN 'age' INTEGER");
}
};
并致电
Room.databaseBuilder(context, RoomDatabaseImpl.class, "Sample.db")
.addMigrations(MIGRATION_1_2)
.allowMainThreadQueries()
.build();
在更改添加AGE
的对象并执行迁移之前,我添加了两个寄存器并且它可以正常工作。
执行迁移后,我只是尝试添加一个新用户:
User user = new User();
user.setName("JoooJ");
user.setId(3);
user.setAge(18);
List<User> userList = new ArrayList<>();
userList.add(user);
App.database(this).userDao().insertAll(userList); // The crash happens here
其他信息:
Android Studio 3和我没有在实际测试中进行测试。
依赖关系:
compile "android.arch.persistence.room:runtime:1.0.0-alpha9-1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha9-1"
compile "android.arch.persistence.room:rxjava2:1.0.0-alpha9-1"
gradle 2.3.3
有人可以帮助我,我真的不知道我做错了什么或者是不是错误。
答案 0 :(得分:37)
错误消息很难解析,但有区别:
TableInfo {name ='user',columns = {name = Column {name ='name',type ='TEXT',notNull = false,primaryKeyPosition = 0},age = Column {name ='age',type ='INTEGER', notNull = true ,primaryKeyPosition = 0},id =列{name ='id',type ='INTEGER',notNull = true,primaryKeyPosition = 1}},foreignKeys = []}发现:
实测值
TableInfo {name ='user',columns = {name = Column {name ='name',type ='TEXT',notNull = false,primaryKeyPosition = 0},id = Column {name ='id',type ='INTEGER',notNull = true,primaryKeyPosition = 1},age =列{name ='age',type ='INTEGER', notNull = false ,primaryKeyPosition = 0}},foreignKeys = []}
年龄可以为空,但是房间预计它不会为空。
将迁移更改为:
database.execSQL("ALTER TABLE 'user' ADD COLUMN 'age' INTEGER NOT NULL");
由于此异常解释非常难以解析,因此我创建了a small script来为您完成差异。
示例:
mig "java.lang.IllegalStateException: Migration failed. expected:TableInfo{name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, age=Column{name='age', type='INTEGER', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}}, foreignKeys=[]} , found:TableInfo{name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}, age=Column{name='age', type='INTEGER', notNull=false, primaryKeyPosition=0}}, foreignKeys=[]}"
结果:
答案 1 :(得分:9)
我也写了一个小的JS脚本,您可以找到https://hrankit.github.io/RoomSQLiteDifferenceFinder/
过程非常简单。
在“期望的”列中输入“期望的错误日志”,即“左一个”。
在“找到的”列中输入“找到的错误日志”,这是正确的。
按Go。按钮。错误日志将转换为JSON。
按“比较”按钮,然后瞧,您将拥有所需的区别。
此插件可从Android Studio Logcat中找出这两个Expected和Found转储之间的差异。
在此处查看比较图像
答案 2 :(得分:6)
在任何链接中,没有一个答案是正确的。经过大量实验,找到了解决之道。需要使用以下方式编写ALTER查询,以使其起作用:
database.execSQL("ALTER TABLE 'user' ADD COLUMN 'age' INTEGER NOT NULL DEFAULT 0")
但是,整数DEFAULT值可以是任何值。
如果要添加“字符串类型”列,请按以下方式添加:
database.execSQL("ALTER TABLE 'user' ADD COLUMN 'address' TEXT")
这就像一种魅力。
答案 3 :(得分:4)
如果要添加Integer type列,请添加此代码
database.execSQL("ALTER TABLE users"
+ " ADD COLUMN year INTEGER NOT NULL DEFAULT 0 ")
答案 4 :(得分:3)
我今天遇到了这个问题,我刚刚将int
中的Integer
字段更改为Entities
。由于int
不能为空,但是Integer
对象可以为空。
答案 5 :(得分:1)
如果您获得的不是notNull差异,则可以简单地使用@NonNull批注标记您的类字段,或者使用ALTER TABLE更改您的sql。但是,如果您遇到不同的列类型差异,例如:TYPE = TEXT,然后找到TYPE =''(COLLATE NOCASE),或者得到了预期的INTEGER,找到INT,则唯一的解决方案是删除并重新创建表。 Sqlite不允许更改列类型。
在Sqlite中使用INTEGER而不是INT,并使用@ColumnInfo(collate = NOCASE)标记Java实体(如果在Sqlite中使用NOCASE)。
在app \ schemas下查看json文件,以获取预期查询的sql。
static final Migration MIGRATION_2_3= new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE IF EXISTS table_tmp");
database.execSQL("CREATE TABLE IF NOT EXISTS `table_tmp` ...");
database.execSQL("insert into table_tmp (`id`, `name` , ...");
database.execSQL("DROP INDEX IF EXISTS `index_table_name`");
database.execSQL("CREATE INDEX IF NOT EXISTS `index_table_name` ON `table_tmp` (`name`)");
database.execSQL("DROP TABLE IF EXISTS table");
database.execSQL("alter table table_tmp rename to table");
}
};
答案 6 :(得分:0)
我在kotlin中没有notNull差异,并且发现了如下异常情况
Expected:
TableInfo{name='enDic', columns={definition=Column{name='definition', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, _id=Column{name='_id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, favourite=Column{name='favourite', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, word=Column{name='word', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, usage=Column{name='usage', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='enDic', columns={usage=Column{name='usage', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, definition=Column{name='definition', type='text', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, _id=Column{name='_id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, favourite=Column{name='favourite', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, word=Column{name='word', type='text', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
然后我使用下面提到的代码来解决该问题
@Entity(tableName = "enDic")
data class Word(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_id")
var _id: Int?,
@ColumnInfo(name = "word")
var word: String?,
@ColumnInfo(name = "definition")
var definition: String,
@ColumnInfo(name = "favourite")
var favourite: Int?,
@ColumnInfo(name = "usage")
var usage: Int?
)
代替此代码
@Entity(tableName = "enDic")
data class Word(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_id")
var _id: Int,
@ColumnInfo(name = "word")
var word: String,
@ColumnInfo(name = "definition")
var definition: String,
@ColumnInfo(name = "favourite")
var favourite: Int,
@ColumnInfo(name = "usage")
var usage: Int
)
答案 7 :(得分:0)
@HRankit 在他的回答中提到的工具:link 我今天尝试时似乎不起作用。如果您也是这种情况,请继续阅读:
如果有人为问题中提到的错误消息而苦苦挣扎,并且有一个包含大量列的巨大表,您可能需要尝试使用 this 在线工具来检查预期和找到的架构。
在生成 <db_version_number>.json
(例如:13.json
)文件之前决定列名和数据类型也非常重要。如果 json 文件已经生成,并且之后您对 Entity 类进行了一些更改,您可能需要删除 json 文件并重建项目以使用正确的值集生成它。
最后,您应该检查有关迁移本身的 sql 语句。
答案 8 :(得分:0)
我遇到了 roomVersion '2.4.0-alpha01' 的问题,这个版本没有为我的情况生成索引表
@Entity(
tableName = "SoundRules",
indices = [
Index(value = ["remoteId"], unique = true)
]
)
我解决了刚刚将房间版本更新为“2.4.0-alpha03”的问题