Room和SQLite:迁移未正确处理实体

时间:2020-06-11 09:31:17

标签: android

我知道有关此问题的一些帖子。但我无法弄清楚。我有一个现有的SQLite数据库。我正在尝试将此数据库迁移到Room。在运行时出现此错误:

 Caused by: java.lang.IllegalStateException: Migration didn't properly handle: offerings(test.db.OfferingEntity).
 Expected:
TableInfo{name='offerings', columns={date=Column{name='date', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, freewill=Column{name='freewill', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, offered=Column{name='offered', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, thanksgiving=Column{name='thanksgiving', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, _id=Column{name='_id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, heave=Column{name='heave', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, experience=Column{name='experience', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, favorite=Column{name='favorite', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, verses=Column{name='verses', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, wave=Column{name='wave', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, vow=Column{name='vow', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
 Found:
TableInfo{name='offerings', columns={date=Column{name='date', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, freewill=Column{name='freewill', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, offered=Column{name='offered', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, thanksgiving=Column{name='thanksgiving', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, _id=Column{name='_id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, heave=Column{name='heave', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, experience=Column{name='experience', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, favorite=Column{name='favorite', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, verses=Column{name='verses', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, wave=Column{name='wave', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, vow=Column{name='vow', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}

区别在于

freewill=Column{name='freewill', type='INTEGER', affinity='3', notNull=true, ...}

freewill=Column{name='freewill', type='INTEGER', affinity='3', notNull=false, ...}

freewill显然需要notNull=true。这是我尝试过的:

1)在我的实体中,我使用了@NonNull批注:

@ColumnInfo(name = FREEWILL)
@NonNull
private int freewill = 0;

此处,错误消息未更改:发生相同的IllegalStateException。

2)在迁移中,我使用了:

database.execSQL("ALTER TABLE " + OfferingEntity.TABLE_NAME + " ADD COLUMN " + OfferingEntity.FREEWILL + " INTEGER NOT NULL DEFAULT 0");

在这里,我收到以下错误消息:

java.lang.RuntimeException: Exception while computing database live data.
Caused by: android.database.sqlite.SQLiteException: duplicate column name: freewill (code 1 SQLITE_ERROR): , while compiling: ALTER TABLE offerings ADD COLUMN freewill INTEGER NOT NULL DEFAULT 0

当然,此列已存在,并且我的代码再次添加了同一列。因此错误。

这是我的数据库类:

@Database(entities = {OfferingEntity.class}, version = 6, exportSchema = false)
public abstract class OfferingsDatabase extends RoomDatabase {

private static final Object LOCK = new Object();
private static OfferingsDatabase INSTANCE;

public static OfferingsDatabase getInstance(Context context) {
    if(INSTANCE == null) {
        synchronized (LOCK){
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(), OfferingsDatabase.class, DbUtil.DB_NAME)
                    .addMigrations(MIGRATION_5_6)
                    .build();
        }
    }

    return INSTANCE;
}

public abstract OfferingsDao offeringsDao();

static final Migration MIGRATION_5_6 = new Migration(5, 6) {
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE " + OfferingEntity.TABLE_NAME + " ADD COLUMN " + OfferingEntity.FREEWILL + " INTEGER NOT NULL DEFAULT 0");
    }
};

}

在此实体:

@Entity(tableName = OfferingEntity.TABLE_NAME)
public class OfferingEntity {
static final String TABLE_NAME = "offerings";
static final String ID = "_id";
static final String FREEWILL = "freewill";


@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ID)
private int id;


@ColumnInfo(name = FREEWILL)
@NonNull
private int freewill = 0;

public int getId() {
    return id;
}

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


public int getFreewill() {
    return freewill;
}

public void setFreewill(@NonNull int freewill) {
    this.freewill = freewill;
}
}

有人对此有解决方案吗?

1 个答案:

答案 0 :(得分:0)

我知道了。我不得不将int更改为Integer。然后它按预期工作。