当前位置: 代码迷 >> 综合 >> Room 数据库迁移采坑记
  详细解决方案

Room 数据库迁移采坑记

热度:30   发布时间:2024-01-13 07:39:01.0

a、采坑之新增表:

1、假设在表UserModel 实体里有一个int字段 id 是主键自增的,在migrate()方法中执行建表SQL语句时,id需要指定 NOT NULL,否则会报异常:java.lang.IllegalStateException: Migration didn't properly handle UserModel 。

2、新建表UserModel 实体时,可以含有boolean类型的字段,但是在migrate()方法中执行建表SQL语句时,该字段不能为BOOLEAN类型的,需要用 INTEGER 替换,且需要加上 NOT NULL,如果不指定默认值,则系统默认为1也就是true。

3、新建表时,在migrate()方法中执行建表SQL语句时,不需要为字段加上默认值即:DEFAULT XXX

b、采坑之新增表字段:

1、假设新增ctTime 字段的类型是int 或 long,在表UserModel 实体里, , 则在migrate()方法中执行SQL语句的时候ctTime 声明需为 INTEGER 类型,并且要加上 NOT NULL DEFAULT 0 ,如:"ALTER TABLE UserModel ADD COLUMN ctTime INTEGER NOT NULL DEFAULT 0" ,
   如果不加 NOT NULL  则会报这个异常:java.lang.IllegalStateException: Migration didn't properly handle UserModel ,因为Room会默认根据你的数据实体UserModel来创建该字段的notNull=true,所以必须加上。
   如果不加 DEFAULT 0 则会报这个异常:android.database.sqlite.SQLiteException: Cannot add a NOT NULL column with default value NULL (code 1):

2、在migrate()方法中执行SQL语句新增某字段时,该字段不能为BOOLEAN类型的,需要用 INTEGER 替换,如果不指定默认值,则系统默认为1也就是true,但是在写表UserModel 实体时,时可以定义Boolean类型的变量的,Room会自己转化为INTEGER。

3、新增某字段类型为 String 时,在migrate()方法中执行SQL语句,该字段用 TEXT 类型进行声明;

 

综合上述情况(a和b):创建Entity实体时,把类型为 int 或 long 或 boolean 的字段用 Integer 去声明,在SQL语句声明时,每个integer字段就 不用加上 NOT NULL,这样创建的表的 Integer 类型的字段,默认值为 NULL,如:database.execSQL("CREATE TABLE IF NOT EXISTS 'UserModel ' ('id' INTEGER NOT NULL PRIMARY KEY autoincrement, 'uid' INTEGER, 'name' TEXT, 'age' INTEGER, 'isMarry' INTEGER)");

另外还有2个注解需要注意如下:

注解 @Ignore         代表字段不会映射到表的 Columns中;
           注解 @Embedded  代表创建嵌套表对象;