场景:在某一个版本升级处,如果使用GreenDao自带的Dao.createTable()来新建表。并且在当前版本或者后续版本做了该表的数据移动,或者使用其他sql语句写成的操作,然后容易导致报错。
报错原因通常会被sql语句try-catch住,而且数据库升级在app启动时期,调试困难比较大。
该问题出在:后续版本中如果对出问题的表进行了列增加,会在前面建表处创建最新的表再进行sql语句操作。但是由于sql语句中字段未覆盖全部数据库字段(已经新增),导致报错走了catch。
例子:
//在某一个版本处升级
case VERSION_32:
//创建新表
KeywordCustomRecordDao.createTable(db,true);
insertNotificationIntoKeywordCustomRecordData(db);
break;
//创建表后做表的数据迁移
private void insertNotificationIntoKeywordCustomRecordData(Database db) {
int customPriority = KeyWordAddFragment.KEY_KEYWORD_PROPERTY;
int i = 0;
Cursor cursor = db.rawQuery("SELECT * FROM NOTIFICATION_KEYWORD", null);
try {
if (cursor != null && cursor.moveToFirst()) {
do {
Long recordId = cursor.getLong(cursor.getColumnIndex("_id"));
String word = cursor.getString(cursor.getColumnIndex("WORD"));
Integer showType = cursor.getInt(cursor.getColumnIndex("SHOW_TYPE"));
Long timestamp = cursor.getLong(cursor.getColumnIndex("TIMESTAMP"));
String recordedSql = "INSERT INTO KEYWORD_CUSTOM_RECORD(_id,NAME,SHOW_TYPE,INCLUDE,EXCLUDE"
+ ",IS_EFFECT,IS_ALL_APP,NOTICE_SETTING,IS_FLOATING,IS_KEYWORD_HIGH,PRIORITY,TIMESTAMP"
+ ",SKY_RULE,SKY_BACKGROUND_URL,SKY_CONTENT,SKY_FLOAT_NOTIFICATION_URL,SKY_POPUP_TITLE"
+ ",SKY_POPUP_CONTENT)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
db.execSQL(recordedSql, new Object[] {recordId, word, 1, word, "", true, true, showType, false, true,
(customPriority + (i++)), timestamp, "", "", "", "", "", ""});
} while (cursor.moveToNext());
}
} catch (Exception e) {
// do nothing
} finally {
if (cursor != null) {
cursor.close();
}
}
}
该操作中,execsql语句执行过程中会因为找不到字段而报错。
解决方法:在创建数据库表后,如果对表进行sql操作,且后续版本会新增字段的话。就不能使用greendao自带的创建数据库表的dao.createTable()操作。而是直接使用sql语句进行表创建,这样创建的表字段和当前版本的字段数量保持一致,从而避免出错。
sql创建表语句例如下:
private void createCustomRecordTable(Database db, boolean ifNotExists) {
String constraint = ifNotExists ? "IF NOT EXISTS " : "";
db.execSQL("CREATE TABLE " + constraint + "\"KEYWORD_CUSTOM_RECORD\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"NAME\" TEXT," + // 1: name
"\"SHOW_TYPE\" INTEGER NOT NULL ," + // 2: showType
"\"INCLUDE\" TEXT," + // 3: include
"\"EXCLUDE\" TEXT," + // 4: exclude
}
以上。